# K1 chat model-usage session
## Public contract
- `ModelUsageSession::default()` creates an unsubscribed session.
- `async fn subscribe(&mut self, adapter: &Adapter, key: String) -> Result<(), ModelUsageSessionError>` installs the key's usage receiver. Repeating the live key is idempotent; a different live key returns `ConflictingKey`.
- `async fn receive(&mut self, durable: &mut DurableThread) -> Result<bool, ModelUsageSessionError>` waits for one observation while subscribed and returns whether one was consumed. An unsubscribed session waits indefinitely; receiver closure flushes pending usage unassociated and returns `false`.
- `async fn drain(&mut self, durable: &mut DurableThread) -> Result<(), ModelUsageSessionError>` persists every currently queued correlated record in order and handles receiver closure.
- `async fn finish_inference(&mut self, durable: &mut DurableThread, key: &str, terminal_agent_response_id: Option<u64>) -> Result<(), ModelUsageSessionError>` drains before supplying the outcome for the active key. Pass `Some` only after durable completion; `None` records failure.
- `async fn restart(&mut self, durable: &mut DurableThread) -> Result<(), ModelUsageSessionError>` drains, persists active pending usage unassociated, and unsubscribes.
- `async fn shutdown(&mut self, durable: &mut DurableThread, active_inference: bool) -> Result<(), ModelUsageSessionError>` drains, records failure for an active inference, persists all remaining usage unassociated, and unsubscribes.
- `fn is_subscribed(&self) -> bool` reports whether one live key and receiver are installed.
- `ModelUsageSessionError` is `Subscription(kcode_k1_codex_adapter::Error)`, `Persistence(String)`, `ConflictingKey { active: String, requested: String }`, or `InvalidState(&'static str)`.
For a practical session, receive and drain work is linear only in observations and correlation records made ready by that call; waiting for a runtime observation is external.