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).| Concept | What it is | How you access it (MCP) | What it returns |
|---|---|---|---|
| State view | A generated snapshot for a view key (view_type, often aligned with template summary_type): blocks of text/JSON produced on a cadence from templates (e.g. symptom snapshot, medication snapshot). | get_view, list_views_and_blocks, get_view_block, get_view_recent_events | Markdown (human-readable) or raw JSON: block content, segments (week / long_term / temp), provenance-style refs depending on tool. Use this when an agent or workflow should consume the same narrative or structured blocks your product shows in the Console. |
| Stable modules | Slow-changing facts: demographics, condition/diagnosis, medications, preferences, etc. | get_stable_data (optional modules filter). | Module-keyed payloads (structured fields), not free-form summaries. Ideal for deterministic steps: eligibility, dosing context, identifiers. |
| Event-state modules | Rolling, event-driven regions (symptoms, labs, adherence, etc.). | list_event_state_modules, get_event_state_module. | Module-typed rolling state (e.g. lists of symptoms, recent events): structured payloads aligned with Patient State module keys. |
| Logs & events | Raw ingestion history and event audit (get_events). | get_logs, get_events. | Rows you can filter by time, log type, or trace for lineage. |
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
| Approach | Typical use |
|---|---|
| MCP Patient State | Runtimes that discover tools (get_stable_data, get_view, get_event_state_module, …) over JSON-RPC. |
| Python SDK Patient State read | Backend jobs already using olira; same semantics as MCP with typed helpers. |
| REST API | Non-Python services; mirror auth and scopes from the SDK. |
Endpoint and credentials (MCP)
Your organization’s MCP URL is in Console → Settings → MCP:Authorization: Bearer <token> on every request:
- Opaque API key (
YOUR_API_KEY) withmcp:patient-state: server-side agents and automation. - Short-lived JWT from
POST /auth/token(exchange API key). - Patient Token: see below; best practice when the agent must only ever see one patient.
- 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: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, thenresources/readbefore the model runs and paste the returnedtextinto 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/readwhen 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.
resources/list: JSON-RPCmethod:resources/list,params:{}. Inspect each entry’suriandnameto decide what to fetch.resources/templates/list: Optional; lists resource templates when the server advertises them (resourceTemplatesin the result).resources/read: Passparams.urifrom the list response. The result includescontentswithtext(often JSON) for that URI.
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/getand 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/list→prompts/getso it stays aligned with what Olira ships.
prompts/list: Discovername, description, and expected arguments schema for each prompt.prompts/get: Passparams.nameand, when required,params.arguments(key/value object matching that prompt’s schema).
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() 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
| Terminal | Returns | Behavior |
|---|---|---|
.execute() | LogQueryResult | All matching rows (or aggregated rows) |
.count() | int | Server-side count only; no rows returned |
.single() | dict | Exactly one row or ValidationError |
.maybe_single() | dict | None | Zero or one row; ValidationError if > 1 |
.as_logs() | list[LogEntry] | Parse rows into typed LogEntry; valid when no .select() was used |
LogQueryResult is iterable, indexable, and len()-able. The async client (AsyncOliraClient) returns AsyncLogQuery with identical interface and async def terminals.
Allowed field roots
The server only allowstype, timestamp, 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.
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 passtoken.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).
mcp:patient-state and pass patient_id explicitly per call instead.
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.
