Agent overview

About the Clinical Trial Matcher

An experimental, evidence-grounded agent that screens a synthetic, de-identified oncology profile against a fictional clinical-trial catalog — with a dedicated evaluation API so the whole run can be inspected end to end.

Research demonstration only. Every trial here is invented. The output is not medical advice and never establishes clinical eligibility. Do not enter real patient data, names, contact details, or record numbers. A qualified study team must review any result.

What it does

A single request turns a free-text, de-identified oncology profile into a criterion-by-criterion comparison against each candidate trial. Three cooperating agents extract the facts, review eligibility with cited evidence, and verify the assembled package; a deterministic rule — not the model — decides each trial's overall status. The service is stateless: nothing is written to disk, and the browser downloads the report locally.

Business requirements

De-identified input only

Direct identifiers (email, phone, SSN, record numbers, explicit names) are rejected before any model call.

Evidence-grounded

Every criterion is judged met, not met, or unknown, and decisive judgements must cite fields from the profile.

Deterministic eligibility

Overall status follows a fixed precedence rule in code, so the model never invents an eligibility verdict.

Independent verification

A verifier audits the assembled package for structural consistency before results are returned.

Fictional catalog

All studies are demonstration data with DEMO- identifiers — never real registry entries.

Stateless & private

No profile is persisted; the report is downloaded client-side and tracing of input text is disabled.

Evaluable end to end

A dedicated API returns the answer plus every tool, context, and metadata value for external eval.

Not medical advice

Results never establish clinical eligibility and always carry an explicit safety notice.

How it works

  1. Safety gateReject the request if the text contains direct identifiers.
  2. Profile extractionAn agent copies only the facts explicitly present into a structured, de-identified profile.
  3. Catalog searchA deterministic lookup selects candidate trials by condition and location.
  4. Eligibility reviewOne agent turn per candidate trial (run concurrently) assesses each criterion with cited evidence.
  5. Deterministic scoringCode derives each trial's overall status and the met / unknown / not-met counts.
  6. Evidence verificationA verifier audits the package; the ranked report is then returned.

The agents

AgentPurposeStructured outputTools
Synthetic profile extractor Extract explicit facts; never infer. PatientProfile None (structured output)
Eligibility evidence reviewer Assess one trial's criteria with cited evidence. EligibilityReview None (structured output)
Screening evidence verifier Audit the package for structural consistency. VerificationResult None (structured output)

All three agents run on the model named by OPENAI_MODEL (default gpt-5-mini). They use structured outputs rather than function tools, so the evaluation trace reports an empty tool list for each — the deterministic catalog search is surfaced as its own operation step instead.

Authentication

The screening endpoints are protected. First exchange your operator credentials (configured with AUTH_USERNAME / AUTH_PASSWORD) for a bearer token, then send it as an Authorization: Bearer <token> header on /api/match and /api/eval. Tokens are short-lived JWTs; missing or expired tokens are rejected with 401. /api/health and the UI stay public.

POST/api/login
curl -X POST http://localhost:8014/api/login \
  -H "Content-Type: application/json" \
  -d '{"username": "admin", "password": "changeme"}'

# → {"access_token": "eyJ…", "token_type": "bearer", "expires_in": 3600}

Evaluation API

POST /api/eval runs the same workflow as /api/match but returns a full trace built for evaluation harnesses: the final answer, plus every step's agent, model, input context, output, available tools, tool calls, guardrail outcomes, response ids, token usage, and timing. Unlike /api/match, it does not fail when the verifier rejects the package — it reports the outcome in metadata.verified so you can score the complete run.

Call it from Postman

POST/api/eval
{
  "profile_text": "Synthetic de-identified profile: 54-year-old female with stage III HER2-negative breast cancer, ECOG 1, located in Berlin."
}

Or with curl (reusing the token from /api/login):

curl -X POST http://localhost:8014/api/eval \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"profile_text": "Synthetic de-identified profile: 54-year-old female with stage III HER2-negative breast cancer, ECOG 1, located in Berlin."}'

Response shape

{
  "request_id": "…",
  "input": { "profile_text": "…" },
  "final_output": { /* same object /api/match returns: profile, matches, verification */ },
  "trace": [
    {
      "index": 1,
      "kind": "agent",
      "name": "profile_extraction",
      "agent_name": "Synthetic profile extractor",
      "model": "gpt-5-mini",
      "input": "…profile text…",
      "output": { /* structured agent output */ },
      "available_tools": [],
      "tool_calls": [],
      "messages": ["…"],
      "guardrails": [{ "name": "deidentified_profile_guardrail", "tripwire_triggered": false }],
      "response_ids": ["…"],
      "usage": { "requests": 1, "input_tokens": 0, "output_tokens": 0, "total_tokens": 0 },
      "duration_ms": 0.0,
      "error": null
    }
    /* … catalog_search (operation), one eligibility_review per trial, evidence_verification … */
  ],
  "metadata": {
    "model": "gpt-5-mini",
    "candidate_trial_ids": ["DEMO-BRCA-001", "…"],
    "verified": true,
    "overall_statuses": ["potentially_eligible", "…"],
    "step_count": 6,
    "duration_ms": 0.0,
    "usage": { "requests": 0, "input_tokens": 0, "output_tokens": 0, "total_tokens": 0 }
  }
}

The interactive schema for every field is available at /docs (import /openapi.json into Postman to generate a collection automatically).