Skip to main content

A code-orchestrated engine that runs the SPARRING method: grounded, cross-vendor adversarial review for AI-in-the-loop decisions.

Project description

Rapier Runtime

A code-orchestrated engine that runs the SPARRING method — grounded, cross-vendor adversarial review for AI-in-the-loop decisions.

Most AI tooling helps you build agent workflows. Rapier is different: it governs them. It runs a structured, adversarial, grounded review over an AI's proposed answer — cross-vendor by construction, with mechanical grounding checks and a correctness gate — so that confident wrongness is structurally hard to ship. The method is SPARRING; Rapier is the runtime that executes it.

Method vs. runtime. SPARRING is the method (the concept, described in its own papers and framework). Rapier is the runtime that executes a SPARRING method declared in a manifest. Upgrade the runtime, or swap a model in a manifest, without changing the method.

Free and open source (Apache-2.0). Not monetized.


Status: pre-alpha — the full ceremony runs end-to-end (M0–M3 complete; M4 in progress)

This is early software, pinned pre-1.0 — but the whole method runs. What works today:

  • The full SPARRING ceremony, end-to-end. The Proposer (divergent generation → false-novelty filter → the Cut — a cross-vendor convergence loop) hands a committed option to the Resolver (author → cross-vendor review → anchored correction → a correctness definitiveness gate → an external-canon citation gate → a two-part report). Run the Resolver alone (spar) or the whole loop (sparring).
  • A front door that types the input (rapier frame). It classifies the input as a question, a proposition, or a hybrid/leaning and routes accordingly — the model judges the type, but the route is decided in code, so a question is never silently graded as though it were a committed decision. A stated decision passes the Presentation (an earnedness check) before it reaches the Resolver; a leaning is seeded into the Proposer's field, where it competes without privilege (--seed). Tune how far the Proposer diverges with --depth shallow|standard|deepshallow is a quick answer, several times faster than the full spread.
  • Cross-vendor by construction. Author and reviewer are always distinct vendors when two keys are present, and it degrades honestly to single-vendor (and says so) when only one is. Any role can be Anthropic, OpenAI, Gemini, Grok, or any OpenAI-compatible endpoint — vendor and model names live only in a manifest.
  • A manifest is the method. Reorder stages, swap a model, or point two roles at two vendors — with no engine-code change. Built-in presets (frame, spar, sparring, proposer) cover the common cases; --settle / --verify tune the resolver, and --depth / --seed tune the proposer.
  • Grounding + a correctness gate. The definitiveness gate checks that every hard specific in the answer is traceable to the given facts or explicitly flagged as an estimate; the citation gate resolves cited external canon (CWE / RFC / DOI / …). Both wrap one shared, battle-tested verification service — no duplicate copies.
  • Auditable by default. Every run persists a redacted, owner-only record (verbatim model-call transcript + per-stage records + verdict + report) to ~/.rapier/runs — no flag required — and the report's THE RECORD section names the path. Opt out per-run with --no-save / RAPIER_NO_PERSIST. Plus env-only secrets + redaction; yaml.safe_load; a threat model and a security policy.

167 tests pass. Cross-vendor runs are live-proven (Anthropic×OpenAI, Gemini×Grok).

Honest boundary. The definitiveness gate, anchored correction, and the two-part trust rider are exploratory governance instruments — useful, but not yet validated by a pre-registered study. Rapier makes confident wrongness structurally harder to ship; it does not make an answer correct.

Quickstart

pip install .          # or: pip install git+https://github.com/muddyone/rapier-runtime.git

export ANTHROPIC_API_KEY=...    # author + gate
export OPENAI_API_KEY=...       # a distinct cross-vendor reviewer
                                # (or GEMINI_API_KEY / XAI_API_KEY)

rapier spar     --request "Should we adopt Kubernetes for one flat-traffic web app?"
rapier sparring --request "Monorepo or separate repos for our three services?"

spar runs the Resolver on a chosen option; sparring runs the full four-phase ceremony. Add --settle N for extra decision-stability rounds, or --verify off|gate|round to tune the citation gate; add --depth shallow|standard|deep (a quick answer vs. the full option spread) or --seed "<option>" (drop a candidate into the field) to tune the Proposer half. Every run is recorded to ~/.rapier/runs (override with --ledger-dir or the RAPIER_RUNS_DIR env var; opt out with --no-save), and the report ends with a THE RECORD section naming exactly where the transcript and records landed.

Not sure an input is even a decision yet? rapier frame --request "…" classifies it (question / proposition / hybrid) and recommends a route, without spending a whole ceremony:

rapier frame --request "Should we adopt Kubernetes for one flat-traffic web app?"
# -> {"input_type": "question", "route": "propose", ...}  (a question — generate first)

No keys? The mock vendor needs none:

rapier run --manifest manifests/echo.yaml --request "should we ship X?"
# -> [mock:rapier-echo-1] should we ship X?

Runtime dependencies are just requests and pyyaml — every vendor is called over the wire; no provider SDKs.

Configure your keys

Rapier reads vendor keys from the environment only — never from a file it reads itself. Scaffold and check your setup:

rapier init      # writes .env.example (key names, no values)
# fill in .env, then load it into your shell:
set -a; source .env; set +a
rapier doctor    # shows which vendors are configured (names only — never values)

doctor reports each vendor's key env var as set/unset and whether cross-vendor review is available (two or more keys). A ceremony launched with no keys fails loudly with an actionable message instead of producing empty output.

Keep your keys loaded

Environment variables last only for the current shell, so source .env sets them up for this session — a new terminal starts empty. That's the same as aws, gh, and most API-key CLIs, and it's deliberate here: Rapier reads keys only from the environment and never persists a secret itself. To avoid re-running the command each time, set it up once:

  • Load in every shell — add the source line to your shell profile (e.g. ~/.bashrc or ~/.zshrc), pointing at a keys file you keep outside any repo:

    # add once to ~/.bashrc
    set -a; source ~/.config/rapier/keys.env; set +a
    

    Simplest for a personal machine. (Trade-off: the keys then load into every shell, and live in a file on disk — fine for your own box, less so on a shared one.)

  • Load per directory — direnv — auto-loads a project's .env when you cd in and unloads it when you leave. Cleaner isolation; a one-time direnv allow per directory.

  • Per session — just run set -a; source .env; set +a when you sit down to use it. Fine for occasional use.

One gotcha: source runs the file as shell, so every value with spaces must be quoted (FOO="a b c", not FOO=a b c) or source will try to run the extra words as a command. If sourcing errors, that's usually the cause.

Use it from an MCP client (optional)

Expose spar / sparring (and a rapier_doctor check) as tools to any MCP client — Claude Desktop, editors, agents:

pip install "rapier-runtime[mcp]"

Point the client at the stdio server. Keys travel in the server's env block — the client launches the process with them, and the engine reads them from the environment (it still reads no secret from a file):

{
  "mcpServers": {
    "rapier": {
      "command": "rapier",
      "args": ["mcp"],
      "env": { "ANTHROPIC_API_KEY": "…", "OPENAI_API_KEY": "…" }
    }
  }
}

Updating & staying current

Check your version, and update to the latest release:

rapier --version                    # what you have (also shown by `rapier doctor`)
pip install -U rapier-runtime       # update to the latest ( add [mcp] if you use the MCP server )

Because Rapier can read files, fetch URLs, and call model vendors, staying current matters for security. How to hear about issues:

  • Security fixes are published as GitHub Security Advisories, which flow into the Python vulnerability databases — so pip-audit and GitHub Dependabot will flag an affected version automatically if you use them.
  • Watch Releases on GitHub (Watch → Custom → Releases) to be notified of new versions.
  • Found a vulnerability? Report it privately — see SECURITY.md. Please don't open a public issue.

Rapier does not phone home to check for updates — nothing about your usage leaves your machine except the model calls you configure.

A manifest is the method

name: echo
pipeline:
  - stage: echo
    config: { note: "hello from Rapier" }
    roles:
      author: { vendor: mock, model: rapier-echo-1 }

Editing the manifest changes the method — reorder stages, swap a model, point two roles at two different vendors — without touching engine code.

Roadmap

Milestone What
M0 Skeleton + threat model + security baseline
M1 Resolver ported (one shared grounding/verification service)
M2 The Proposer (convergence primitive; SPARK / Pattern Lock / the Cut; cross-vendor roles)
M3 Full controller + the spar / sparring adapters (the whole ceremony end-to-end)
M4 Hardening + packaging + first public release in progress

Development

pip install -e '.[dev]'
pytest -q

License

Apache-2.0. See LICENSE.


Rapier Runtime and the SPARRING method are projects of ResourceForge.

Project details


Download files

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

Source Distribution

rapier_runtime-0.4.0.tar.gz (202.2 kB view details)

Uploaded Source

Built Distribution

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

rapier_runtime-0.4.0-py3-none-any.whl (132.9 kB view details)

Uploaded Python 3

File details

Details for the file rapier_runtime-0.4.0.tar.gz.

File metadata

  • Download URL: rapier_runtime-0.4.0.tar.gz
  • Upload date:
  • Size: 202.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for rapier_runtime-0.4.0.tar.gz
Algorithm Hash digest
SHA256 6a19cf8aed6ca3167b71280d5bb244b77a9a358ea329175d984ed60112e46dbb
MD5 1028d2a777086999f67b2548a1da60b9
BLAKE2b-256 0c2843a68cd6315a1cd615ec03542c27b32c18c7cdd560895da286afdc971c15

See more details on using hashes here.

File details

Details for the file rapier_runtime-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: rapier_runtime-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 132.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for rapier_runtime-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 173c43e9cfd173807511cb41f3a4d53f980491dcd9ff844936f836a98b22f1b8
MD5 edc4b763855c5b70a8c4fdc14f770ad5
BLAKE2b-256 0f5e2855aad11955db223f9b6ee6d88ff3610e08d2be1a83d36a798a88ac10c5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page