Skip to main content

Runtime-Neutral Agent Engineering

CI PyPI Downloads Python License: MIT

Discover capabilities. Verify execution. Control collaboration.

Runtime-Neutral Agent Engineering is the engineering layer between agents and the runtimes they depend on. It discovers coding-agent CLIs, validates what they can actually prove, admits them to a verified pool, and orchestrates their work under explicit budgets and loop protection.

Agent runtime ≠ agent orchestration. Runtimes execute; this project engineers the layer above them. It is not a chatbot, a model provider, a single-runtime wrapper, a remote agent network, an A2A implementation, a distributed execution platform, or a multi-agent network.

What it does provide today: Remote Collaboration across a real process boundary — you declare an agent (identity, role, runtime binding), compose a remote session with one call, and exchange verified task packets with an agent running in its own process, on your machine, under the same contract-first discipline as the local pipeline. See Remote Collaboration (V3.1).

Agent runtime support today: ✅ Claude Code CLI — implemented + REAL-verified · ✅ Codex CLI, Pi — REAL-verified in the audited multi-runtime four-stage E2E · ⚠️ Gemini CLI, Qwen Code, OpenCode, Cline, tiny-agents — adapter implemented, offline-tested (not REAL-verified in this repository). Details in Agent Runtime Support.

What's new

Remote Collaboration (V3.1) — declared agents now collaborate across a real process boundary:

  • Declare an agent (identity + role + runtime binding) → compose a remote session → send a task packet → receive the result packet. One honest round trip per interaction, verified end-to-end with the real Claude CLI.
  • Try it in 30 seconds — offline, no runtime, no login, no configuration:
git clone https://github.com/Tsubasa-Kaede/runtime-neutral-agent-engineering.git
cd runtime-neutral-agent-engineering
python examples/remote_offline_demo.py
  • With the Claude Code CLI installed and logged in, examples/remote_real_claude.py runs the same flow against a real provider. Details in Remote Collaboration (V3.1).

Previously: the installed CLI became a self-contained product — dual-agent qualify (gated G1–G14 qualification, persisted VERIFIED + REAL evidence), dual-agent run / run --observe (reads persisted evidence only, never auto-qualifies), stable exit codes with stdout-machine-JSON / stderr-human-diagnostics, python -m dual_agent, and product-only packaging.

Contents: What's new · Overview · Why · Quick Start · Integration · Agent Runtime Support · Agent Runtime Ecosystem · Installation · Configuration · Core Concepts · Architecture · Modes · Agent Collaboration · Remote Collaboration (V3.1) · Extending Runtime · Security · Testing · Verification Status · Release · Limitations · Contributing · License

Overview

What — a runtime-neutral agent engineering and orchestration layer that sits between your application and the coding-agent CLIs it drives.

Why — orchestration logic keeps getting hard-coupled to one runtime. This layer decouples the two: your application talks to the engine, and the engine discovers, verifies, and orchestrates whatever runtime you plug in through the adapter contract. Your code never binds to Claude Code or any other runtime by name.

What it does — the layer provides:

  • Runtime Discovery — is a runtime present at all?
  • Runtime Validation — gated qualification runs (G1–G14) producing real evidence
  • Capability-based Selection — selection by proven capability, never by name
  • Agent Orchestration — architect → coder → tester → reviewer stage chains
  • Structured Collaboration — validated packets over an append-only ledger
  • Budget Control — invocation slots reserved before every call
  • LoopGuard — duplicate / repeated-failure / cycle protection before spend
  • Provenance — every validation result carries OFFLINE or REAL evidence
  • Security Boundary — no-secrets contract, content scanning, protected paths

Product flow — one local product entry, two strictly separated commands:

dual-agent qualify   Discovery → Health → gated G1–G14 Qualification
                     → VERIFIED+REAL Evidence persisted to disk
dual-agent run       Verified Runtime selection → four-stage execution
                     (architect → coder → tester → reviewer) → Collaboration
                     packets over the ledger → closed JSON summary
dual-agent run --observe   + execution observation events streamed to stderr

run reads persisted evidence and never automatically qualifies; qualify is the only command that performs qualification. See Modes.

What it supports — support is reported at two strictly separated levels: REAL VERIFIED · adapter implemented. The Agent Runtime Support section defines each level, and Agent Runtime Ecosystem lists the runtimes with actual integration evidence in this repository.

Current Runtime Integration

  • 3 REAL VERIFIED — Claude Code CLI, Codex CLI, Pi (audited multi-runtime four-stage E2E, 2026-09)
  • 5 adapter-level — Gemini CLI, Qwen Code, OpenCode, Cline, tiny-agents
    • more via the ExternalAgentAdapter contract

These counts describe this repository's integrations, not the size of the agent ecosystem.

Why

Problem How this project addresses it
Orchestration logic coupled to one specific runtime Runtime-neutral engine core; runtimes plug in through an adapter contract. No runtime, provider, or model name is hard-coded in the engine
Runtime state is opaque — installed? logged in? working? Discovery and Health are explicit, structured checks with closed state vocabularies
Capability and health get conflated Health (READY) and capability (proven evidence) are separate layers; neither implies the other
Multi-agent collaboration lacks structured contracts Stages exchange typed packets through a protocol contract and an append-only ledger — never raw model output
Real verification is unclear or claimed without evidence Provenance is enforced: the runner refuses to grant REAL without real-call evidence; Offline validation is not REAL validation
Agent calls have no unified budget TaskBudget spans one task lifecycle with reserve-before-invoke semantics
Multi-stage work lacks loop protection LoopGuard pre-checks duplicates, repeated failures, and cycles before any spend
Runtime-specific logic pollutes the orchestration layer Adapters own all runtime specifics; the orchestrator only sees the adapter protocol

Quick Start

Install the published package from PyPI — Python >= 3.10, zero runtime dependencies, no clone needed:

pip install dual-agent-development==2.3.0
dual-agent --version
dual-agent --help

Name map: the GitHub repository is runtime-neutral-agent-engineering; the PyPI distribution is dual-agent-development (import dual_agent, console script dual-agent).

First real run — qualify once, then run tasks (both commands are part of the installed CLI; no source checkout needed):

dual-agent qualify                                       # gated G1–G14 qualification; persists VERIFIED+REAL evidence
dual-agent run "Add a slug helper and its test"          # reads persisted evidence
dual-agent run --observe "Add a slug helper and its test" # + execution events on stderr

On a machine with no persisted evidence, run exits 2 with a machine-readable reason (NO_EVIDENCE_NO_QUALIFIER) and a human hint pointing at dual-agent qualify — it never automatically qualifies and never falls back to offline execution. REAL qualification requires RUN_REAL_PROVIDER_TESTS=1; offline qualification results are reported honestly and are never persisted.

Or try it in 30 seconds from a fresh clone — offline, no runtime, login, or configuration needed:

git clone https://github.com/Tsubasa-Kaede/runtime-neutral-agent-engineering.git
cd runtime-neutral-agent-engineering
python examples/offline_mock_run.py

Expected output — a closed, secret-free JSON summary:

{"path": "FOUR_STAGE", "status": "SUCCESS", "stages": ["architect","coder","tester","reviewer"], ...}

Remote Collaboration in 30 seconds

Same clone, still offline — one declared agent, one real process boundary, one task packet round trip:

python examples/remote_offline_demo.py

Expected output — a closed JSON summary naming the composed agent, the derived remote address, and the packet it produced (scripted adapter, clearly labeled as an offline demonstration). With the Claude Code CLI installed and logged in, examples/remote_real_claude.py performs the same exchange with a real provider. See Remote Collaboration (V3.1).

Examples are repository examples: they come with a source checkout and are not included in the wheel or site-packages. pip install gives you the package and the dual-agent CLI; running the examples requires a clone of this repository.

To run real tasks through the CLI, see Installation (environment setup) and Modes (CLI usage). To connect a real runtime or your own application, see Integration.

Integration

Three on-ramps, from a 30-second offline taste to a real application.

How it fits

User Application
      ↓
Host / Facade  (ProductionFacade via host.py)
      ↓
Runtime Discovery  →  Runtime Health  →  G1–G14 Qualification (gated)
      ↓
Verified Runtime Pool  (VERIFIED + REAL evidence only)
      ↓
Orchestration  (Budget reserve + LoopGuard before every invoke)
      ↓                                  ↓
Claude Code CLI                  Your runtime adapter
(verified integration)           (implement ExternalAgentAdapter)

The agent runtime is an external dependency, never a component of this project: the engine discovers, verifies, and orchestrates; the runtime executes.

Try Offline

git clone https://github.com/Tsubasa-Kaede/runtime-neutral-agent-engineering.git
cd runtime-neutral-agent-engineering
python examples/offline_mock_run.py
  • No runtime, no login, no credentials, no network
  • Runs the real ProductionFacade end to end with mock adapters
  • Prints one closed, secret-free JSON summary

Run with Claude Code

RUN_REAL_PROVIDER_TESTS=1 is a safety gate, not a test-only switch: real runtime health checks and real invocations — in the gated tests and in minimal_host_app.py alike — run only when it is explicitly set in the environment. It exists so a real call can never happen by accident; do not bypass or hard-code it.

# Windows (cmd)
set RUN_REAL_PROVIDER_TESTS=1
python examples/minimal_host_app.py "Add a slug helper and its test"

# Windows (PowerShell)
$env:RUN_REAL_PROVIDER_TESTS="1"
python examples/minimal_host_app.py "Add a slug helper and its test"

# macOS / Linux
RUN_REAL_PROVIDER_TESTS=1 python examples/minimal_host_app.py "Add a slug helper and its test"

The first run performs the gated G1–G14 qualification (several minutes) and admits the runtime to the Verified Runtime Pool; that qualification evidence is then reused across tasks instead of re-running per task. The example fails honestly — non-zero exit, one-line reason — when the CLI is absent, not logged in, or fails qualification. It never falls back to mock or offline execution.

Responsibility Boundary

Responsibility Scope Execution Boundary
Claude Code installation and authentication Claude Code CLI installation, authentication, and PATH availability External to this project
REAL runtime opt-in Setting RUN_REAL_PROVIDER_TESTS=1 when REAL tests are intentionally executed Explicitly controlled outside the project
Protected-path declaration Paths required by the G13 protection gate Declared by the execution environment
Runtime qualification and orchestration Discovery, health checks, G1–G14 qualification, Verified Pool admission, orchestration, budget enforcement, and LoopGuard Handled by the project
Credentials and runtime configuration API keys, login/logout, and runtime configuration Not accessed or managed by the project

The project does not install, authenticate, or manage Claude Code or its credentials. It invokes an already installed and configured runtime through the ExternalAgentAdapter contract.

REAL Runtime Usage

The currently REAL-verified runtime is Claude Code CLI. The user installs and authenticates Claude Code through its own tooling; this project invokes the already configured runtime through the ExternalAgentAdapter contract. This project never installs or logs in to Claude Code, never manages its credentials, and never modifies its runtime configuration.

The REAL dual-agent collaboration fact base (one REAL-verified runtime — not two runtimes):

  • two role-qualified agent invocations (architect and coder)
  • Architect → CollaborationPacket → transport → Coder → reply
  • provenance=REAL on both envelopes
  • one shared correlation_id across both legs
  • delivery receipts DELIVERED in both directions
  • no fallback and no mock standing in for REAL

Integrate into Your Application

The same chain as a library (runnable file: examples/minimal_host_app.py):

import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "dual-agent-development" / "scripts"))

from claude_code_adapter import ClaudeCodeAdapter
from generic_runtime_health import GenericRuntimeHealth
from host import build_facade_from_bootstrap
from mode_gate import Mode
from real_validation_executor import run_real_validation
from runtime_adapter_registry import (
    AdapterDescriptor, AdapterRegistry, discovery_sources)
from runtime_discovery import RuntimeCandidateDiscovery

adapter = ClaudeCodeAdapter.from_environment()   # None when not installed
if adapter is None:
    raise SystemExit("Claude Code CLI not found on PATH")

registry = AdapterRegistry()
registry.register(AdapterDescriptor(
    runtime_id="claude-cli", provider_id="anthropic", model_id=None,
    runtime_type="coding-agent", display_name="Claude Code",
    adapter_factory=lambda: adapter, config_fingerprint="installed"))

def qualify(instance):
    validation, _ = run_real_validation(
        instance, instance.probe, timeout_seconds=300.0,
        protected_paths=(Path.home() / ".claude" / ".credentials.json",))
    return validation

health = {}
for candidate in RuntimeCandidateDiscovery(
        discovery_sources(registry)).discover_all():
    if candidate.available:
        item = registry.get(candidate.runtime_id)
        checked = GenericRuntimeHealth().check(candidate, item.adapter_factory())
        health[candidate.runtime_id] = checked.status

facade = build_facade_from_bootstrap(
    registry, qualifier=qualify, current_health=health)
result = facade.run(task_id="my-task", task=task, prompt=task, mode=Mode.ON)

facade.run omits provenance on purpose: the HostFacade labels every run from the qualification evidence, so a real run can never be mislabeled OFFLINE at the CLI seam. To drive the same facade from the dual-agent CLI, inject it — cli.main._facade = facade — see Modes.

For any other runtime, implement the six-method adapter contract — see Extending Runtime.

Agent Runtime Support

This project does not bundle, replace, or depend on a specific agent runtime. It integrates with external coding-agent CLIs through adapters, and support is reported at two strictly separated levels:

  • REAL VERIFIED — an adapter ships in this repository, discovery works, offline tests cover it, and a gated REAL qualification run produced VERIFIED + REAL evidence with Verified Runtime Pool admission.
  • Adapter implemented — an adapter ships and is covered by offline tests, but no REAL qualification run has ever been performed for it. Adapter implemented, but not REAL-verified.

Runtime Compatibility Matrix

Agent Runtime / Tool Adapter Discovery Offline Tests REAL Verification
Claude Code CLI claude_code_adapter.py claude executable available on PATH tests/test_claude_health.py ✅ REAL VERIFIED — Discovery → Health → G1–G14 qualification → Verified Pool admission → REAL dual-agent collaboration (v2.1.227)
Codex CLI codex_adapter.py codex executable available on PATH tests/test_codex_adapter.py ✅ REAL VERIFIED — audited multi-runtime four-stage E2E (2026-09)
Pi pi_adapter.py pi executable available on PATH tests/test_pi_adapter.py ✅ REAL VERIFIED — audited multi-runtime four-stage E2E (2026-09)
Gemini CLI gemini_adapter.py gemini executable available on PATH tests/test_gemini_adapter.py ❌ Not run on the reference machine (no gemini installed); gated REAL test assets ship in the suite
Qwen Code qwen_adapter.py qwen executable available on PATH tests/test_qwen_adapter.py ❌ Not performed
OpenCode opencode_adapter.py opencode executable available on PATH tests/test_opencode_adapter.py ❌ Not performed
Cline cline_adapter.py cline executable available on PATH tests/test_cline_adapter.py ❌ Not performed
tiny-agents tiny_agents_adapter.py Runtime entry provided by TINY_AGENTS_AGENT_PATH / TINY_AGENTS_COMMAND tests/test_tiny_agents_adapter.py ❌ Not performed

What "Supported" Means

Support is reported at exactly two levels:

  • REAL VERIFIED — an adapter is implemented and has passed real runtime qualification / REAL verification.
  • Adapter implemented — an adapter is implemented and covered by offline tests, but REAL runtime verification has not been performed.

Treat an adapter-implemented runtime as unverified until you run a REAL qualification in your own environment.

Which runtime should I use?

If you use… Do this
Claude Code CLI Supported today (REAL VERIFIED) — Integration → "Run with Claude Code"
Codex CLI / Pi REAL VERIFIED in the audited multi-runtime E2E — install the CLI yourself, log in through its own flow, then dual-agent qualify in your environment
Gemini CLI / Qwen Code / OpenCode / Cline Adapter is ready: install the CLI yourself, log in through its own flow, then REAL-verify it in your environment before production use
tiny-agents Adapter is ready: install the executable, set both TINY_AGENTS_* variables, then REAL-verify it in your environment before production use
Your own CLI or runtime Implement the six-method ExternalAgentAdapter contract; the orchestrator never needs modification

Current Support Boundary

Three runtimes — Claude Code CLI, Codex CLI, and Pi — hold REAL-proven capability evidence in this repository (Claude Code individually and in the audited multi-runtime four-stage E2E). Nothing else is supported in the verified sense, and the boundary is enforced by the engine itself: no admission without VERIFIED + REAL evidence, and no fallback to weaker paths.

Agent Runtime Ecosystem

This section lists the runtimes that currently have actual integration evidence in this repository — a shipped adapter and, where stated, REAL verification. It makes no claim about tools not listed here.

Tool / Runtime Category Integration Status
Claude Code CLI Coding Agent CLI REAL VERIFIED
Codex CLI Coding Agent CLI REAL VERIFIED (multi-runtime four-stage E2E, 2026-09 audit)
Pi Coding Agent CLI REAL VERIFIED (multi-runtime four-stage E2E, 2026-09 audit)
Gemini CLI Coding Agent CLI Adapter implemented
Qwen Code Coding Agent CLI Adapter implemented
OpenCode Multi-provider coding agent harness Adapter implemented
Cline Coding Agent CLI Adapter implemented
tiny-agents (Hugging Face) Minimal Agent Runtime Adapter implemented

The "Integration Status" column uses two fixed values: REAL VERIFIED and Adapter implemented. Gemini CLI, Qwen Code, OpenCode, Cline, and tiny-agents are adapter-implemented, but not REAL-verified.

Installation

Python 3.10+ (3.10 / 3.11 / 3.12 tested in CI). The engine is pure standard library with zero runtime dependencies. Published on PyPI as dual-agent-development — install from the registry or from source:

Option 1 — Install from PyPI (recommended)

The published distribution — no clone, no build step:

pip install dual-agent-development==2.3.0
  • Distribution dual-agent-development on PyPI — note the GitHub repository name (runtime-neutral-agent-engineering) and the PyPI package name are different
  • Installs the dual_agent package, the dual-agent console script, and the skill assets (SKILL.md, references, templates, agents, examples)
  • Python >= 3.10, zero runtime dependencies; dual-agent --version verifies the install

Option 2 — Clone and Run

The fastest first taste: nothing is installed, and the example runs straight from the checkout.

git clone https://github.com/Tsubasa-Kaede/runtime-neutral-agent-engineering.git
cd runtime-neutral-agent-engineering
python examples/offline_mock_run.py
  • Python 3.10+ is the only prerequisite
  • No agent runtime required, no login, no credentials, no network
  • No package installation for the offline example

Option 3 — Editable Installation

The regular development setup:

git clone https://github.com/Tsubasa-Kaede/runtime-neutral-agent-engineering.git
cd runtime-neutral-agent-engineering
python -m venv .venv

.venv\Scripts\activate          # Windows
# source .venv/bin/activate     # macOS / Linux

python -m pip install -e .
dual-agent --version

This installs the dual_agent package (mapped from dual-agent-development/scripts/), the dual-agent console script, and the skill assets (SKILL.md, references, templates, agents, examples). For development on the engine itself, pip install -e . from a checkout is the editable equivalent of the PyPI install.

Option 4 — One-command Bootstrap

python scripts/bootstrap.py

The bootstrap creates (or reuses) .venv, installs this project into it, and prints the next steps. It installs this project only: it never installs or logs into a third-party agent runtime, never reads secrets or .env files, and never modifies system-level configuration, PATH, or shell profiles. --check runs a no-side-effect preflight (Python version and repository layout — no files created, no network used):

python scripts/bootstrap.py --check

Install with an AI Coding Agent

You can hand the setup to a user-side coding agent (Claude Code, Codex CLI, Gemini CLI, Cursor, Cline, ...) with a prompt like:

Clone this repository, inspect its README installation instructions, create the recommended Python environment, and install this project only. Then run dual-agent --version and the offline smoke example, and report the result. Do not install any third-party Agent Runtime. Do not read or configure API keys, secrets, or credentials, and do not log in to or out of any service. Do not modify system-level configuration.

This is user-side assistance — not a dependency of this project, and not a statement that these agents are integrated or verified by it.

Configuration

Runtime Configuration

No project-specific runtime configuration file is required. The engine reads environment variables when the corresponding runtime integration uses them.

Variable Purpose
RUN_REAL_PROVIDER_TESTS Enables gated REAL runtime tests when set to 1
TINY_AGENTS_AGENT_PATH Path to the tiny-agents agent executable or configuration
TINY_AGENTS_COMMAND Command used to invoke the configured tiny-agents agent

These variables are optional. They are not required for the core engine or for the currently verified Claude Code path.

Runtime prerequisites (runtime-level, not dependencies of this package):

Runtime Prerequisite
Claude Code CLI claude on PATH, logged in through its own flow (the CLI itself requires Node.js)
Codex CLI codex on PATH, logged in through its own flow
tiny-agents Executable + both environment variables above

Additional behavior is set through constructor parameters, not environment: mode is a CLI flag (--mode), and health-check timeouts are parameters (discovery checks use 10 s; the minimal health check is capped at 30 s).

Secrets: never put API keys or tokens in the repository, in examples, or in committed environment files. The engine never reads, stores, prints, or modifies credentials; runtime authentication belongs to the runtime, not to this layer.

Core Concepts

Concept Meaning
Runtime Discovery Does the runtime exist? (DISCOVERED / NOT_FOUND)
Runtime Health Is it usable right now? (READY / AUTH_REQUIRED / UNAVAILABLE / ERROR)
Agent Capability What a runtime has proven it can do (architecture, coding, testing, review) — built only from gate evidence, never from declarations
Candidate Validation The gated qualification run (G1–G14) over a runtime candidate
Verified Runtime A runtime whose validation concluded VERIFIED with REAL provenance
Runtime Selection Choosing agents by verified capability subset; the verified path is score-less and never falls back to the ready pool
Mode Gate Caller intent: OFF / AUTO / ON routing
Collaboration Packet The protocol contract between stages — who owes what work, on a frozen envelope schema
Collaboration Transport The delivery mechanism — an in-process mailbox today
Provenance Evidence class of a validation result: OFFLINE (mock) or REAL (real calls under an explicit gate)
Task Budget Per-task invocation accounting; a call either happened-and-was-paid or never happened
LoopGuard Pre-invoke protection against duplicate tasks, repeated failures, and cycles

Architecture

Two execution paths share one engine; the entry point decides which runs:

flowchart TD
    T[Task] --> MG["Mode Gate: OFF / AUTO / ON"]
    MG --> CL["Classifier: SIMPLE / MEDIUM / COMPLEX / UNRESOLVED"]

    subgraph VP["Verified path (production stack)"]
        D["Runtime Discovery"] --> H["Runtime Health"]
        H --> Q["Qualification G1-G14 (gated)"]
        Q --> V["Verification: VERIFIED + REAL"]
        V --> ADM["Verified Runtime Pool admission"]
        ADM --> SEL["Verified selection (score-less)"]
    end

    subgraph RP["ReadyPool path (classic engine)"]
        H2["Runtime Health"] --> CAP["Capability Registry"]
        CAP --> POOL["ReadyPool"]
        POOL --> SSE["Scored selection"]
    end

    CL --> VP
    CL --> RP
    SEL --> EX["Execution: architect - coder - tester - reviewer"]
    SSE --> EX
    EX --> G["Per-invoke gates: Handoff - LoopGuard - Budget reserve - Invoke"]
    G --> OUT["Closed, secret-free summary"]
  • The ReadyPool path (classic engine) admits runtimes on health and scores candidates from registry evidence.
  • The Verified path (production stack) requires a gated qualification run, VERIFIED + REAL evidence, and Verified Runtime Pool admission before execution — and it never falls back.
  • Load-bearing invariant: the verified path never silently borrows the ReadyPool. An empty verified selection normalizes to NO_CAPABLE_AGENT instead of consulting the ready-pool registry, and the verified orchestrator executes with an empty fallback policy.
  • The five distinctions the engine never blurs: Discovery ≠ Health, Health ≠ Qualification, Qualification ≠ Verification, Verification ≠ Admission, READY ≠ VERIFIED.

Task lifecycle: one ProductionFacade owns exactly one task. Budget, guard, and ledger are per-task and never reset between runs. SINGLE path: at most 1 real invocation. Four-stage path: at most 4 (each role exactly once); beyond that, BUDGET_EXHAUSTED. A new task needs a new facade.

Remote collaboration layering

Remote collaboration reuses the same engine discipline one level up: the local side declares and composes; the remote side runs in its own process and answers under the same packet contract. Five steps, one honest round trip:

you                                          remote agent (own process)
──                                          ─────────────────────────
1  declare: identity + role + binding
2  compose: build_remote_session(...)  ───► child process starts
                                             3  endpoint reads the task packet
                                             4  runtime CLI → real model
                                                 (scripted adapter in the
                                                 offline demo)
                                             5  output parsed through the
                                                 same packet contract
6  receive: result packet              ◄───┘
7  close: the interaction ends

The boundary carries packets only — never conversations, never credentials — and a delivery receipt never claims execution. See Remote Collaboration (V3.1).

Modes

The dual-agent console script is self-contained: it composes the default host stack (environment discovery → health observation → persisted evidence → Verified Runtime Pool → facade) and runs the task. Two commands, strictly separated:

dual-agent qualify                                          # the only command that qualifies
dual-agent run --mode off  "Implement a GitHub webhook"
dual-agent run --mode auto "Implement a GitHub webhook"
dual-agent run --mode on   "Implement a GitHub webhook"
  • qualify performs the gated G1–G14 qualification over discovered runtimes and persists VERIFIED + REAL evidence under ~/.dual-agent/qualification/. REAL invocation requires RUN_REAL_PROVIDER_TESTS=1; offline results are reported honestly and are never persisted.
  • run only reads persisted evidence. With no evidence it exits 2 with a machine-readable reason (NO_EVIDENCE_NO_QUALIFIER) and a human hint pointing at dual-agent qualify — it never automatically qualifies and never re-qualifies implicitly.

Observation: --observe streams human-readable execution events to stderr while stdout stays exactly one machine-readable JSON line:

dual-agent run --observe "Implement a GitHub webhook"

stdout/stderr contract: the execution result is one closed, secret-free JSON line on stdout (exit 0 on SUCCESS, 2 on any closed failure word); human diagnostics and observation go to stderr.

Honest limitation: the engine layer still never creates runtimes, adapters, or credentials. Embedding applications that want full control over the composition can inject a pre-configured facade directly:

from dual_agent import cli
cli.main._facade = my_configured_facade   # embedding surface, unchanged

See examples/offline_mock_run.py for constructing the facade from real engine components, examples/minimal_host_app.py for the full REAL-path chain (discovery → qualification → facade), and host.py (build_facade) for the host-facing construction API.

Mode Behavior
OFF No orchestration; returns the delegated empty result — never silently runs
AUTO (default) Classify the task; SIMPLE / MEDIUM / UNRESOLVED take the single-agent path, COMPLEX takes the dual-agent path
ON Force the dual-agent path (architect + coder; tester + reviewer when qualified candidates exist)

Task classification is a closed keyword table (SIMPLE / MEDIUM / COMPLEX / UNRESOLVED) — a deterministic classifier, not a model. Tasks with no keyword hit classify as UNRESOLVED and take the orchestration path.

Without verified tester / reviewer candidates, dual-agent success is reported as NO_VERIFICATION_CAPABILITY — never a silent two-stage success, never a fabricated four-stage success.

Failures are structured and terminal; downstream stages do not run after an upstream failure:

  • *_INVOKE_FAILED, *_PACKET_INVALID — a stage failed on the runtime or the packet contract
  • MISSING_HANDOFF — a required upstream packet is absent from the ledger
  • BUDGET_EXHAUSTED, LOOP_GUARD_REJECTED — task-lifecycle guards
  • NO_CAPABLE_AGENT, NO_VERIFICATION_CAPABILITY — no verified candidates

Honest retries require a new task_id; the loop guard rejects re-running the same stage of the same task.

Agent Collaboration

Four stages, four contracts:

Architect
    ↓  ArchitecturePacket
Coder
    ↓  ImplementationPacket
Tester
    ↓  TestPacket
Reviewer
    ↓  ReviewPacket
Role Reads Produces
architect the task itself ArchitecturePacket
coder architecture packet wire text ImplementationPacket
tester latest implementation packet TestPacket
reviewer architecture + implementation + test ReviewPacket

Two layers that are easy to conflate but are not the same:

  • CollaborationPacket is the protocol contract — who owes what work, on a frozen envelope schema.
  • Transport is the delivery mechanism — an in-process mailbox for local collaboration, or a real subprocess stdio boundary for remote collaboration (single machine). There is no network transport, no A2A protocol, no distributed execution, and no multi-agent network.

Remote Collaboration (V3.1)

Declared agents collaborating across a real process boundary, on one machine: the remote agent runs in its own process, receives one task packet, and answers with one result packet. The whole exchange is contract-driven — the remote side sees exactly the task packet, never a conversation, never your credentials.

The user flow is five steps:

declare   an agent: identity + role + runtime binding   (AgentManifest)
compose   one call: build_remote_session(registry, agent_id, role, you)
send      one task packet (session.send)
receive   one result packet (session.receive)
close     the session when the interaction ends          (session.close)

Agent address. Every participant has an opaque address of the form agent:{agent-id}:{role} — for example agent:my-coder:coder. Addresses are stable logical names: they contain no runtime, provider, or model facts, and they survive rebinding to a different runtime.

Delivery is not execution. A DELIVERED receipt means the remote process received the task packet — nothing more. Execution success shows up as a valid, parsed result packet on receive(). The vocabulary never blurs the two.

Two experiences, one flow:

Offline demo REAL example
Entry python examples/remote_offline_demo.py python examples/remote_real_claude.py
Remote side a scripted adapter module (examples/scripted_coder.py), clearly labeled the real Claude Code CLI → real provider
Prerequisites Python only — no runtime, login, or configuration Claude Code CLI installed on PATH and logged in through its own flow
Result closed JSON summary, provenance honestly OFFLINE closed JSON summary from real model output

Both run from a source checkout (examples are repository examples — see the note in Quick Start). The remote collaboration flow is verified end-to-end with the real Claude CLI; the same declaration pattern works for the other adapters shipped by this project.

Common failures

Failure What it means What to do
ValueError: unknown agent: … No agent with that id is registered Check the id you pass to build_remote_session against your registry
ValueError: role not declared by agent: … The agent's declaration does not include that role Declare the role in the manifest, or compose a role the agent declares
ValueError: adapter factory is not remotely constructible The manifest's factory cannot be carried across the process boundary Build it with importable_adapter_factory
ValueError: profile conflicts with agent binding: … The adapter profile and the runtime binding declare different runtime facts Make runtime/provider/model identical in both declarations
FAILED receipt The child process failed (bad import, adapter construction, or crash); diagnostics are captured from its stderr Check the failure reason printed by the example; verify the module path
ModuleNotFoundError in child diagnostics The declared module was not importable by the remote process For a custom adapter module, pass its directory as source_path
Claude CLI not found The real example requires the Claude Code CLI Install it, log in through its own flow, retry — the example exits non-zero and never falls back
provenance: OFFLINE on a real run The composition did not carry REAL qualification evidence — reported honestly, never faked Expected for plain example runs; REAL provenance requires the qualified path

Extending Runtime

Adding a runtime means implementing the adapter contract — the architecture allows it, and you own the adapter and its verification.

New runtimes integrate through the ExternalAgentAdapter protocol (dual-agent-development/scripts/external_agent_adapter.py) with six methods — three core invocation methods plus three health methods:

Core invocation:

  • discover()RuntimeDiscovery — is the runtime present?
  • invoke(request)InvocationResult — run one agent request
  • cancel(invocation_id)InvocationResult — cancel an in-flight invocation

Health (required to pass the health pipeline and G1-G14 qualification):

  • check_authentication()AuthenticationCheck — observe the runtime's own read-only auth state
  • check_provider_model()ProviderModelCheck — gated on observed authentication, never guessed
  • minimal_health_check(timeout_seconds)MinimalHealthCheck — honest skipped/unsupported without the REAL gate

A runtime whose CLI has no observable authentication surface cannot be faked into this shape — see the runtime's adapter notes for its declared conformance level.

Adapters own all runtime specifics — executable resolution, authentication state, subprocess environment (whitelisted: PATH / HOME / USERPROFILE / SYSTEMROOT), error normalization. The orchestrator only sees the protocol, so adding a runtime never means modifying the orchestrator.

Registration goes through the runtime adapter registry (runtime_adapter_registry.py, register(AdapterDescriptor)) and the discovery bootstrap (discovery_bootstrap.py). The full contract is documented in dual-agent-development/references/adapter-contract.md, and adapter_probe.py is a small developer probe for exercising an adapter by hand.

Note: there is no third-party plugin package API in this release — extending means implementing the protocol inside a checkout, as the built-in adapters do.

Security

  • No-secrets contract: raw output, secrets, and model reasoning never enter packets, the ledger, traces, or public results; content_safety is the single scan authority.
  • Raw-output quarantine: stage inputs are always upstream packets; raw output must pass the packet contract and content scan before reaching the next stage.
  • Protected paths: REAL validation snapshots caller-declared protected files (credentials / config); any change during the run fails gate G13.
  • Minimal environment: adapters start subprocesses with a whitelist env (PATH / HOME / USERPROFILE / SYSTEMROOT) — credential-bearing variables are never forwarded.
  • Safe error normalization: adapter error text is shape-scrubbed before reaching traces or reports.
  • The engine never reads, stores, prints, or modifies credentials; never logs in or out; never touches runtime configuration. Authentication belongs to the runtime.
  • Real runtime calls are opt-in and off by default (RUN_REAL_PROVIDER_TESTS=1 gates the real tests).
  • CLI output is a closed allow-list summary.

Testing

Offline Tests

python -m pytest tests/ -q                     # offline suite + gated skips
python -m unittest discover -s tests           # equivalent stdlib runner
python -m compileall -q dual-agent-development # syntax gate

Offline baseline: 2177 passed / 24 skipped / 520 subtests in the development workspace, which carries two protected local test assets; a clean checkout reports 2150 passed / 31 skipped / 520 subtests. Skips are opt-in REAL-gated entries, plus — on a clean checkout — missing protected local test assets.

REAL Runtime Tests

REAL tests invoke real runtimes and require a logged-in claude on PATH:

# Windows (cmd)
set RUN_REAL_PROVIDER_TESTS=1
python -m pytest tests/test_rc3_real_discovery.py -v -s

# Windows (PowerShell)
$env:RUN_REAL_PROVIDER_TESTS="1"
python -m pytest tests/test_rc3_real_discovery.py -v -s

# macOS / Linux
RUN_REAL_PROVIDER_TESTS=1 python -m pytest tests/test_rc3_real_discovery.py -v -s

This qualification run takes several minutes, produces VERIFIED + REAL evidence with all four capabilities, and admits the runtime to the Verified Runtime Pool. One sanctioned qualification is then reused across tasks — the runtime is never re-qualified per task.

A dual-agent collaboration smoke, gated by RUN_REAL_PROVIDER_TESTS=1 (tests/test_collaboration_session.py, Claude Code CLI v2.1.227), additionally proves the architect → packet → transport → coder → reply loop end to end: two real invocations under two role-qualified agent addresses on one REAL-verified runtime, provenance=REAL on both envelopes, one shared correlation_id, DELIVERED receipts in both directions, and credential-file invariance across the run.

Verification Status

Area Status
Runtime Discovery Implemented + offline-tested
Runtime Health Implemented + offline-tested
Capability Validation (G1–G14) Implemented + offline-tested
Verified Runtime Pool Implemented + offline-tested
Agent Selection (both paths) Implemented + offline-tested
Collaboration contract & packets Implemented + offline-tested
Local transport Implemented + offline-tested
Remote transport Real subprocess stdio boundary (single machine) — no network transport
Remote collaboration (declare → remote session → result packet) ✅ Real verified — end-to-end with the real Claude CLI: real provider, real model output through the packet contract
Four-stage orchestration Implemented; proven end-to-end offline
Dual-agent collaboration (architect → coder) ✅ Real verified — one REAL-verified runtime, two role-qualified agent invocations, provenance=REAL both directions (gated tests/test_collaboration_session.py)
Multi-runtime four-stage execution (claude + codex + pi) ✅ Real verified — audited multi-runtime E2E, each runtime qualified and admitted before execution (2026-09)
Claude Code CLI REAL verification ✅ Real verified — full chain, v2.1.227, all four capabilities, pool admission
Codex CLI / Pi REAL verification ✅ Real verified — audited multi-runtime four-stage E2E (2026-09)
Gemini CLI / Qwen Code / OpenCode / Cline adapters Implemented + offline-tested; REAL verification not performed
tiny-agents REAL verification Not performed (adapter implemented; offline-tested)
Installed CLI surface (qualify / run / --observe) Implemented + offline-tested + packaging smoke (build → isolated venv install → console & module entries)
Provenance enforcement Implemented — the runner refuses REAL without real-call evidence
Security boundary Implemented + offline-tested (content safety, protected paths, env whitelist)

Release

Distribution version: 2.3.0 (dual-agent --version; single source of truth dual_agent.__version__, read dynamically by the build). Latest tagged GitHub release: Runtime-Neutral Agent Engineering v2.3.0. The 2.3.0 distribution adds Remote Collaboration — declare → compose → send → receive → close across a real process boundary, with repository examples and honest offline/REAL provenance.

Limitations

  • Three runtimes (Claude Code CLI, Codex CLI, Pi) hold REAL-proven evidence from audited runs; the Gemini CLI, Qwen Code, OpenCode, Cline, and tiny-agents adapters ship offline-tested but without repository-run REAL verification. Treat every adapter as unverified until you run dual-agent qualify in your own environment.
  • Runtime availability depends on your environment: PATH executables, login state, and (for tiny-agents) two environment variables. Missing pieces mean honest absence, never partial registration.
  • Task classification is a closed keyword table, not a model.
  • The dual-agent path covers architect + coder; tester + reviewer run as verification stages gated on dual-agent success.
  • Qualification is a point-in-time proof; stability over repeated runs is a separate measurement, not a guarantee.
  • Package maturity: pre-1.0. The installed-CLI surface (qualify, run --observe, the persisted evidence store under ~/.dual-agent/qualification/) is new (2026-09) and may still change shape.
  • Remote collaboration runs across a real process boundary on a single machine — no network transport, no A2A, no cross-machine execution.

Contributing

Simple GitHub workflow:

  1. Fork the repository
  2. Create a branch for your change
  3. Make the change
  4. Run the offline suite (python -m pytest tests/ -q) and keep it green
  5. Open a Pull Request

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dual_agent_development-2.3.0.tar.gz (238.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dual_agent_development-2.3.0-py3-none-any.whl (265.7 kB view details)

Uploaded Python 3

File details

Details for the file dual_agent_development-2.3.0.tar.gz.

File metadata

  • Download URL: dual_agent_development-2.3.0.tar.gz
  • Upload date:
  • Size: 238.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dual_agent_development-2.3.0.tar.gz
Algorithm Hash digest
SHA256 6c2a978fdf52a5e9692a70e990fc6e82f7406be5bdffcc98d9aa4b7e1e6da88f
MD5 440f81921bfc5ead5e54f3e4e36a34b5
BLAKE2b-256 938cf99b7e85b627061ac669d59d0d2a15a5155d77d7066756cd1cedb2f21e48

See more details on using hashes here.

Provenance

The following attestation bundles were made for dual_agent_development-2.3.0.tar.gz:

Publisher: publish.yml on Tsubasa-Kaede/runtime-neutral-agent-engineering

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dual_agent_development-2.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for dual_agent_development-2.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aed8eaf020894d06d7d5bc42156fff6d4e11b4726e60569edc0e87df624c7b9b
MD5 cf5fc4c0945d3ccfb634af77d7977836
BLAKE2b-256 9002c896dce5290d99536a00d9d9f08d3afe3a7bff232c4b64cc225ea02d04ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for dual_agent_development-2.3.0-py3-none-any.whl:

Publisher: publish.yml on Tsubasa-Kaede/runtime-neutral-agent-engineering

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

2.3.0 This release

2 files

2.2.1

2 files

2.2.0

2 files

2.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page