Skip to content

Coordinate with Oncofiles #452 — agent_state patient_id migration (migration 061) #406

Description

@peter-fusek

Sibling ticket to oncofiles#452

Oncofiles v5.12 plans to ship a schema change on the `agent_state` table (migration 061) that adds a `patient_id` column. This ticket tracks Oncoteam's side of the coordinated rollout.

Oncofiles meta: oncofiles#453 (v5.12 Sprint)
Architecture memo: `docs/architecture/option_a_scoping_decisions.md` in Oncofiles repo
Blast radius: touches both projects — Oncoteam is the primary writer of `agent_state`

Current state (pre-migration)

Oncofiles' `agent_state` table has:

  • `agent_id` (e.g. 'oncoteam')
  • `key` (e.g. 'last_briefing_date')
  • `value` (JSON string)
  • UNIQUE constraint on `(agent_id, key)`

The latent leak: if an Oncoteam agent sets `agent_state('last_briefing_date', '2026-01-15')` while processing Patient A, then switches to Patient B, the `get_agent_state('last_briefing_date')` call returns Patient A's date. Classic cross-patient state collision.

Originally identified as "Finding 6" in the closed oncofiles#406 thread but never individually ticketed.

Post-migration state

Oncofiles migration 061 will:

  1. `ALTER TABLE agent_state ADD COLUMN patient_id TEXT`
  2. DROP the UNIQUE index on `(agent_id, key)`
  3. CREATE a new UNIQUE index on `(agent_id, key, patient_id)`
  4. Update 3 Oncofiles MCP tools (`set_agent_state`, `get_agent_state`, `list_agent_states`) to accept `patient_slug` per Option A

What Oncoteam needs to do

1. Update every `set_agent_state` / `get_agent_state` / `list_agent_states` caller

Audit Oncoteam's codebase for all `call_oncofiles('set_agent_state', ...)` and `call_oncofiles('get_agent_state', ...)` invocations. Each must pass `patient_slug` matching the currently-active patient for the agent task.

Today's pattern (unscoped):
```python
call_oncofiles('set_agent_state', {'key': 'last_briefing_date', 'value': '2026-04-21'})
```

Post-migration pattern (scoped):
```python
call_oncofiles('set_agent_state', {'key': 'last_briefing_date', 'value': '2026-04-21', 'patient_slug': patient_slug})
```

2. Decide the legacy-data policy

Oncofiles migration 061 has two options for existing rows:

  • (a) Populate `patient_id` on existing rows with the default patient (preserves data, risks wrong attribution if multi-patient agents wrote to same key)
  • (b) NULL out existing rows with log line per affected agent (safest, forces re-write, acknowledges legacy data is untrustworthy)

Oncoteam preference needed. The safer option (b) means any Oncoteam agent state built up since deployment will be wiped; agents must rebuild their state per-patient on first run post-migration. Option (a) preserves history but may tie a value to the wrong patient.

3. Schedule coordinated deploy

Sequence matters:

  1. Oncofiles ships migration 061 + updated MCP tools (accepts both slug and legacy no-slug callers during grace period)
  2. Oncoteam updates all callers to pass `patient_slug`
  3. Oncofiles sets `DEPRECATED_LEGACY_AGENT_STATE=true` (starts warning on no-slug callers)
  4. After 1 week of zero warnings: Oncofiles removes legacy fallback
  5. Close oncofiles#452 + this ticket

4. Pattern to mirror for Oncoteam's own agent_state-like tables

If Oncoteam has any similar `(agent_id, key) → value` tables scoped globally rather than per-patient, audit them now. Same leak risk.

Timeline

References

  • Oncofiles sprint: oncofiles#453 (v5.12 meta)
  • Scoping memo: oncofiles `docs/architecture/option_a_scoping_decisions.md`
  • Original "Finding 6" context: oncofiles#406 (closed)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions