# Health patterns for AI agents (beta)

> What changed in a patient's record and what recurs, computed by fixed statistical rules: trends, deviations from the person's usual level and symptom recurrence, each with its period, evidence and limitations; not diagnoses.

Source: https://developers.anpheros.com/guides/health-patterns

**Anpheros computes what changed in a patient's record and what recurs, by fixed statistical rules, and hands each finding to your application or AI agent with its period, the resources behind it, the method version and its limitations.** A model no longer has to guess a trend from a handful of numbers: it gets the trend, the uncertainty around it and the data to cite.

Beta: available with sandbox credentials only (`sk_test_…` keys and sandbox OAuth connections). Production records are not analysed yet.

## What it finds

| Type | Question it answers | Method |
|---|---|---|
| `trend` | Is a measurement going up or down over the window? | Theil–Sen slope with Mann–Kendall on one value per day (weekly medians for dense watch data), corrected when neighbouring days are alike |
| `trend` (`change_between_results`) | How did a lab test with two to five results change? | First and last result, with the latest against the report's reference range; described, not tested |
| `trend` (`event_rate_change`) | Is a symptom recorded more or less often? | Symptom days over days the person logged anything, last 30 days against the 90 before, exact test |
| `baseline_deviation` | Is the last week unusual for this person? | Last 7 days against days 8–60, Mann–Whitney or an autocorrelation-adjusted difference of means |
| `recurrence` | Do symptom episodes come back at regular intervals? | Intervals between episode starts, seeded Monte Carlo against episodes placed at random |

All tests of one run are corrected together (Benjamini–Hochberg). A finding is `statistically_supported` only when the corrected q-value is below 0.05 **and** the change is at least the threshold for that measurement.

## What it is not

- **Not a diagnosis.** Findings describe the record; they never name a condition or recommend a treatment change. Every finding carries `safety.not_a_diagnosis = true` and `safety.causal_claim = false`.
- **Not a cause.** A change after a new medication, or two things recorded together, is not evidence that one caused the other.
- **Not an AI model, and not clinically reviewed yet.** Every number comes from fixed, versioned statistical rules; no AI model analyses the data. The thresholds for a meaningful change were set with AI assistance and have not yet been reviewed by a clinician; each finding says so in `review.thresholds_reviewed_by_clinician`. The engine is validated on synthetic patients with known planted patterns: it finds what was planted and stays quiet when nothing was. That is not clinical validation.

## Try it

```bash
curl -s https://platform.anpheros.com/v1/patients/$PATIENT/patterns?window_days=180 \
  -H "Authorization: Bearer $ANPHEROS_KEY"
```

With the TypeScript SDK, from its next release (the published version does not include these methods yet):

```ts
const run = await anpheros.patterns.run(patientId, { window_days: 180, min_strength: 'moderate' });
for (const f of run.findings) console.log(f.summary_text, f.strength, f.limitations.map(l => l.code));
```

With the MCP server, ask your agent *"What changed in this patient's record over the last six months?"*: it calls `get_health_patterns`, and can follow up with `get_pattern_evidence`, `get_series` and `compare_periods`. `POST /v1/context` adds a `patterns` section for questions about change and relationships, or when you ask for the `patterns` need.

## Endpoints

| Endpoint | What it returns |
|---|---|
| `GET /v1/patients/{id}/patterns` | a run: findings, what could not be computed and why, what consent left out; filters `window_days` (30–730), `end`, `types`, `min_strength` |
| `GET /v1/patients/{id}/patterns/{finding_id}` | one finding, recomputed for the same window |
| `GET /v1/patients/{id}/patterns/{finding_id}/evidence` | every supporting resource, paged |
| `GET /v1/patients/{id}/series?code=…` | one measurement as one value per day, with coverage, gaps and source changes |
| `POST /v1/patients/{id}/patterns/compare` | one measurement in two periods you choose |

## Reading a finding

- `summary_text`: one plain sentence, safe to show or quote.
- `strength`: `strong`, `moderate`, `weak` or `not_tested`. Weak and untested findings are descriptions, not evidence.
- `window`, `comparison_window`: the periods analysed.
- `evidence` (up to 20, spread over the period) and `evidence_total`: the resources behind the finding, with version, date, value and author type.
- `limitations`: coded, with text. Show them with the finding.
- `review`: whether a clinician has reviewed the thresholds (`false` for now) and where they come from.
- `method`, `engine_version`, `input_fingerprint`: the same data, configuration and versions give the same result and the same id.

## Rules worth knowing

- **Consent first.** Under an OAuth grant the engine reads only what the grant allows; what it could not read is listed in `omitted`, without content.
- **Ids.** Patients appear with your project's pairwise id; finding ids are derived per project. When the record changes, a finding gets a new id and the old one answers 404.
- **Time.** Days are UTC days; the person's local time is not in the record yet, so time-of-day patterns are not computed.
- **Left out.** Values written by AI, results marked entered-in-error and dates known only to the month are not used, and are counted.
- **Limits.** 30 pattern runs per minute per credential, on top of the usual 600 requests per minute.

## Frequently asked questions

### Does it use a language model?
No. Every number comes from fixed, versioned statistical methods. Any model, hosted or local, can read the results.

### Why is a clear change in my data marked weak?
Because the evidence does not survive the correction for all the tests in the run, the series is short or noisy, or the change is below the threshold for that measurement. The finding still describes what the record shows.

### When will it work on production records?
Production records will be analysed only under a patient's OAuth consent that includes the separate `anpheros/patterns` permission, which the consent screen shows on its own line. Production API keys stay closed. It opens after the privacy policy is updated; until then it answers 403 for production credentials.

## Related

- [FHIR MCP server for AI agents](https://developers.anpheros.com/guides/mcp)
- [LLM applications and healthcare data](https://developers.anpheros.com/guides/llm-healthcare-data)
- [AI agents and medical data](https://developers.anpheros.com/guides/ai-agents-medical-data)
- [Healthcare API with patient consent](https://developers.anpheros.com/guides/healthcare-api-patient-consent)
