Skip to main content
This guide covers reading compiled patient data from your backend or agent runtime (after logs have been ingested) via the MCP Patient State server, the SDK state-read APIs, or REST with the same auth rules.

State views vs state modules (what to call, what you get)

Downstream workflows usually need either rendered views (summaries your templates generate) or raw module payloads (structured regions of patient state). For a workflow that must branch on “what the clinician sees in the chart summary,” start from views (get_view / blocks). For rules that depend on structured facts (medication list, diagnosis codes), use stable or event-state modules. Combine both when an agent needs narrative plus verifiable fields.

Choose an access path

Endpoint and credentials (MCP)

Your organization’s MCP URL is in Console → Settings → MCP:
Send Authorization: Bearer <token> on every request:
  1. Opaque API key (YOUR_API_KEY) with mcp:patient-state: server-side agents and automation.
  2. Short-lived JWT from POST /auth/token (exchange API key).
  3. Patient Token: see below; best practice when the agent must only ever see one patient.
  4. Auth0 JWT from olira login: interactive developer sessions.

Agent frameworks

OpenAI Agents SDK: attach the MCP base URL and headers so tools load from Olira:
LangChain / LangGraph: point an MCP adapter at the same URL with streamable_http and the same Authorization header.

Using MCP resources

Resources carry patient state (and related organization) context as URI-addressable snapshots (constitution-backed sections, population-view material, or other canonical blobs) over the same MCP base URL as tools. Design choice: decide whether each resource’s content should land directly in the prompt or stay behind runtime fetch.
  • Inject into the prompt: Call resources/list, pick the URIs that matter for this workflow, then resources/read before the model runs and paste the returned text into your system prompt, developer message, or user preamble. Best when you want deterministic, fixed context every turn and accept the token cost up front.
  • Expose at runtime: Register resources with your agent runtime (when it supports MCP resources) so the model can request resources/read when it chooses, similar to tools. Best when context is large or optional and you want the agent to pull only what it needs, trading a round-trip for a smaller default context.
Flow:
  1. resources/list: JSON-RPC method: resources/list, params: {}. Inspect each entry’s uri and name to decide what to fetch.
  2. resources/templates/list: Optional; lists resource templates when the server advertises them (resourceTemplates in the result).
  3. resources/read: Pass params.uri from the list response. The result includes contents with text (often JSON) for that URI.
Provider and organization API keys may see additional organization-scoped resources merged into resources/list; behavior depends on auth context. Same Authorization header as tools. If your stack does not surface MCP resources in the agent UI, call these JSON-RPC methods from your integration layer and inject or bridge the text yourself.

Using MCP prompts

Prompts are reusable templates for different use cases (for example missing-data elicitation or provider alerts). They guide behavior in two ways:
  • In-session: Resolve with prompts/get and apply the messages as system / developer instructions, or prepend to the user turn, so the same agent follows Olira’s intended tone and structure.
  • Across channels: The resolved text can be sent directly to other parties or surfaces: a patient-facing message to probe for missing information, a provider alert, or any template meant to be delivered as-is outside the main chat. You still obtain the canonical wording via prompts/listprompts/get so it stays aligned with what Olira ships.
Typical flow:
  1. prompts/list: Discover name, description, and expected arguments schema for each prompt.
  2. prompts/get: Pass params.name and, when required, params.arguments (key/value object matching that prompt’s schema).
Enable prompts/list and prompts/get when your framework supports them. If the runtime only exposes tools, call these methods over the same POST /mcp JSON-RPC transport yourself, or copy template text into your own prompts until wiring is complete; see MCP → Resources and prompts for method names.

Querying logs (filter / project / aggregate)

get_logs() is a simple time-cursor fetch. When you need richer filtering, field projection, or server-side aggregation, use the log query builder (sdk:state-read scope).

Single-patient queries

Organization / cohort queries

population_logs / PopulationLogs posts to POST /v1/state/logs/query (no patient_id in the path). Omit patient_ids to span the whole org; pass a list for a cohort.

Terminals at a glance

LogQueryResult is iterable and indexable. Python also exposes AsyncOliraClient / AsyncLogQuery; .NET exposes *Async methods on OliraClient / LogQuery.

Allowed field roots

The server only allows type, timestamp, ingested_at, trace, and payload as filter/projection root paths. Any other root (e.g. id, user_id) returns HTTP 422, which the SDK surfaces as ValidationError.
  • timestamp — when the clinical event happened (the patient’s timeline)
  • ingested_at — when the platform received it (poll/audit; only moves forward)
To page for newly landed data, filter on ingested_at rather than timestamp — a historical import can have a timestamp from months ago and an ingested_at from today:

Patient-scoped tokens (single-patient agents)

Best practice: when an agent or client must only access one patient’s data (for example a patient-facing assistant), mint a Patient Token on your server and pass token.access_token as the Bearer credential. The token binds to that patient_id; callers cannot substitute another patient, which reduces cross-context contamination (no accidental mixing of patients in one session).
Fields and expiry are documented under Patient token in the SDK reference. For provider or backend agents that legitimately need to switch patients, use an API key with mcp:patient-state and pass patient_id explicitly per call instead.

Batch export (Parquet zip)

For offline analytics, use the SDK Exports APIs (sdk:state-read): create_export → poll get_exportdownload_export for a short-lived presigned URL to a ZIP of typed Parquets (logs, state_modules, view_blocks, events, extracted). Select patients by patient_ids, cohort_id, or scope="project". See create_export and the other methods under SDK → Exports.

Prompting

Use only the tools your workflow needs. MCP exposes many tools (get_stable_data, get_view, get_event_state_module, get_logs, …). Registering or describing the smallest set that satisfies each agent or step keeps context windows smaller, cuts redundant round-trips, and usually improves latency and cost. Prefer narrow calls: e.g. get_stable_data with a modules filter instead of pulling every stable module when you only need medications; request raw format when the model must parse JSON, markdown when a short human-readable summary is enough. For resources and prompts, follow Using MCP resources and Using MCP prompts above; they use the same MCP endpoint as tools with resources/list, resources/read, prompts/list, and prompts/get. Match tool choice to the task (see the State views vs state modules table above): narrative or chart-aligned answers → views (get_view / blocks); rules, scoring, or integrations → stable or event-state modules; audits or lineage → logs / events (get_events). Avoid adding unrelated state to the prompt; retrieve in steps and only escalate to broader tools if the first pass is insufficient. Scope credentials the same way: Patient Tokens for a single patient session; broader API keys only where the workflow must switch patients. Tighter scope reduces risk of cross-patient mistakes and keeps prompts aligned with one person’s data. Choose get_view when you need template-driven output; get_stable_data / get_event_state_module when you need authoritative structured slices for logic or validation.