BYO keys & BYO harness

This is the integration contract for design partners — not optional enterprise fluff. ReasonRank is built so your LLM spend and your agent runtime stay yours. If you already have (or will build) an eval harness, CI job, or VPC agent, start here. ReasonRank scores and decides; it does not require you to rip out your runner.

Four key types (do not conflate)

KeyWherePurpose
Provider keys (BYOK)Settings → ProvidersOffline evals, judges, online scoring — AES-256-GCM at rest
Ingestion keys (rr_ingest_…)Settings → IngestionPOST /api/ingest + OTLP
PATs (rr_pat_…)Settings → API KeysPublic API, CLI, gateway recording, external cell submit
Platform envVercelStripe, Resend, encryption master key — never customer LLM keys

Connection defaults (Azure endpoint / api-version, Bedrock region, openai_compatible base URL) live on providerCredentials.config. Per-model overrides on Model Configs still win.

Agent execution modes

Set on the agent (Settings card on /tasks/[id]Execution):

ModeWho runs the agentWhen to use
provider (default)ReasonRank calls the model via BYOKPrompt / model comparison suites
http_endpointReasonRank POSTs each case to your HTTPS URLYour agent is reachable from the internet
externalYour worker submits cell outputs via APIVPC / firewalled / CI-local harness

All three feed the same score → rank → recommend → verify loop.

Customer harness / agent
        
        ├─ http_endpoint ◄── signed POST from ReasonRank
        
        └─ external ──────── POST /api/v1/runs/:id/cells (PAT)
                
                
         scoreOutput  metrics  NI gate  recommendations

Mode A — HTTP endpoint (push)

  1. Agent → Execution mode → HTTP endpoint
  2. Set HTTPS URL (SSRF-blocked: no localhost / private / metadata IPs)
  3. Optional hostname allowlist
  4. Generate signing secret (shown once) — store in your agent
  5. Implement POST handler:

Request (JSON):

{
  "runId": "",
  "caseId": "",
  "attempt": 1,
  "modelConfigId": "",
  "modelName": "gpt-4o-mini",
  "provider": "openai",
  "input": "last user turn",
  "turns": [{ "role": "user", "content": "" }],
  "systemPrompt": ""
}

Headers:

  • X-ReasonRank-Timestamp — unix ms
  • X-ReasonRank-SignatureHMAC-SHA256(secret, "${timestamp}.${rawBody}") hex

Response (JSON):

{
  "output": "agent final answer",
  "tokensInput": 120,
  "tokensOutput": 40,
  "costUsd": 0.002,
  "latencyMs": 800
}

output is required; tokens/cost/latency optional but needed for honest $/success.

Verify signature with ±5 minutes skew. Reject unsigned requests.

Mode B — External cells (pull / BYO harness)

  1. Agent → Execution mode → External
  2. Start a run (UI, POST /api/v1/runs, or reasonrank run)
  3. Run status becomes awaiting_external; every grid cell is parked
  4. Your harness POSTs results:
curl -X POST "$APP/api/v1/runs/$RUN_ID/cells" \
  -H "Authorization: Bearer rr_pat_…" \
  -H "Content-Type: application/json" \
  -d '{
    "cells": [{
      "modelConfigId": "",
      "testCaseId": "",
      "attempt": 1,
      "output": "",
      "tokensInput": 100,
      "tokensOutput": 50,
      "costUsd": 0.001,
      "latencyMs": 400
    }]
  }'

Idempotent on (modelConfigId, testCaseId, attempt). When every cell is terminal, the run completes and recommendations can regenerate.

This is the “bring your own harness” path — Braintrust-style local runners, CI jobs, internal eval frameworks all submit here.

Shortcut: reasonrank run --local is a first-party harness over this same API — it starts a run with a per-run executionMode: "external" override (no agent reconfiguration needed), executes the grid on your machine with your own env provider keys, and submits cells here. The server does all scoring, so local, CI, and cloud runs share one stats → non-inferiority path. Recorded tool-call episodes replay via reasonrank replay (design-partner preview).

Skills as versioned artifacts

  1. Skills → Register skill (name should match OTel toolName / skill span)
  2. Attach an agent suite (eval cases)
  3. Register versions (semver + optional checksum)
  4. Detail page shows 30d span rollups (invocations, error rate, spend)
  5. Run the attached suite with any execution mode above

Skills do not yet have a separate apply/recommend path — production model switches stay on the agent. The skill object makes marketing claims truthful: versioned artifact + suite + production telemetry.

CI gating (same math as Savings)

export REASONRANK_API_KEY=rr_pat_…
pnpm --filter @reasonrank/cli exec tsx src/cli.ts run \
  --agent "$AGENT_ID" --models "$BASELINE,$CANDIDATE" --wait

pnpm --filter @reasonrank/cli exec tsx src/cli.ts assert \
  --run "$RUN_ID" --baseline "$BASELINE"

Fails if there are fewer than 5 shared cases or the paired-cluster 95% CI lower bound on quality delta is below -0.02. See /docs/ci-gating and the .github/actions/reasonrank-gate composite action.

Security guarantees

  • BYOK ciphertext is AES-256-GCM, key-versioned (v1.…); rotate via CREDENTIALS_ENCRYPTION_KEY_V1
  • Endpoint invoke: HTTPS-only in prod, SSRF IP blocklist, optional host allowlist, HMAC
  • External cells: PAT scope runs:write, org-scoped; cross-tenant IDs 404
  • Gateway is self-hosted single-tenant only — never put customer provider keys through a shared ReasonRank host
  • Ingest defaults to metadata-only; payloads are opt-in + retention-swept

Minimal “first dollar of value” path

  1. BYOK → Settings → Providers
  2. Create agent + 5+ test cases
  3. Ingest real traffic (SDK / OTel) or set monthly volume override
  4. Run evaluation across 2 models → apply recommendation
  5. Confirm verified savings after switch detection (≥20 post-switch traces)