# Async Runtime OpenRath v1.2 adds an internal async runtime for model calls, tool dispatch, and persistence. The public API is still synchronous: users call `agent(session)` or `run_session_loop(...)` and receive a `Session`. ```{figure} ../_static/async-runtime.svg :alt: Internal async runtime The private runtime can advance model, tool, and persistence work concurrently while preserving the synchronous public API. ``` ## Public Boundary | Surface | Contract | | --- | --- | | `rath._async` | Private implementation detail; do not import it in user code. | | `run_session_loop(...)` | Synchronous public function. | | returned `Session` | May be lazy internally, but exposes stable identity, lineage, and sandbox ownership immediately. | | `chunk_table` / `cumulative_usage` | Reading either property synchronizes pending async work. | | `Session.synchronize()` | Explicit wait point for pending work. | ## Lazy Session Lazy output sessions let OpenRath return a session object before every internal append is fully materialized. This keeps lineage and ownership composable while allowing background work to finish safely. | Read | Behavior | | --- | --- | | `id`, `parent_session_ids`, `lineage_kind` | Eager metadata. | | `sandbox`, `sandbox_backend` | Eager ownership and placement. | | `chunk_table` | Waits for pending loop work. | | `cumulative_usage` | Waits, then returns accumulated usage. | ## Parallel Tool Dispatch Tools expose a concurrency key through `FlowToolCall.resource_key(arguments)`. | Key relationship | Scheduler behavior | | --- | --- | | same key | Run serially. | | distinct keys | May run concurrently. | | default unsafe tool | Uses `("global",)`, so it serializes with other unsafe calls. | | `parallel_safe=True` | Default key becomes `("safe", tool.name)`. | This keeps the model transcript deterministic: tool result rows are appended in the original tool-call order even if execution finishes out of order. ## Persistence And Crash Detection Async persistence writes the same JSONL session format as the synchronous path. During in-flight writes it also creates a `.__partial__` marker; a clean trailer removes the marker. Listing or loading persisted sessions can therefore report an interrupted run without guessing from file timestamps. ## Failure Semantics | Failure | User-visible behavior | | --- | --- | | tool exception | Written as structured JSON `tool_result` and sent back to the model. | | invalid tool args | Written as `invalid_tool_arguments`. | | unknown tool | Written as `unknown_tool`. | | streaming unsupported by client | Raises `TypeError` before registering the loop output. | | lazy work failed | Raised when synchronizing the session. | ## Stability Note Document only these behavior boundaries. `rath._async` names, task classes, writer internals, and event-loop choices are private and may change across minor releases. [← Developer Notes](index.md)