# Open-format K1 Chat State 0.8.0
`ActorState` adds provider-free scheduling to Chatend's open `ChatBox` format. It reexports `ChatBox`, `BoxId`, `DispatchedToolCall`, `ProviderCall`, `RecoveryError`, `ToolCallId`, and `TransitionError`, plus Chatend's public open-string conventions. A `ChatBox` has a consecutive one-based ID and accessible `box_type`, `contents`, `hidden_type`, and `hidden_contents` accessors. Types and hidden conventions are open strings, not enums.
```rust
let mut state = ActorState::new(false);
state.accept_user("hello".into())?;
let start = state.begin_inference()?.unwrap();
state.append_stage(start.job, "thinking".into(), vec![])?;
state.complete_inference(start.job, "answer".into())?;
# Ok::<(), StateError>(())
```
`accept_box` preserves arbitrary four-field boxes. `accept_system`, `accept_user`, and `accept_attachment` create canonical triggering arrivals. Tool returns use Chatend's correlated, non-exhaustive conventions.
`accept_tool_message` creates a canonical Tool Message but never schedules inference or a follow-up. `accept_async_return` creates a Tool Result v1, and `accept_async_return_v2` creates a metadata-bearing Tool Result v2; both result methods trigger scheduling identically. An idle Tool Message therefore leaves `begin_inference` unready, while an idle Tool Result makes it ready.
During an active round, arrivals retain FIFO order. Tool Messages alone do not create a follow-up, including when they arrive after a flush. A Tool Result creates one coalesced follow-up unless a nonempty active-arrival flush consumes it. Generic boxes and system, user, and attachment arrivals remain triggering.
`begin_inference` opens a provider round without adding a box. Job IDs are process-local and monotonic; `frontier` is the previous last box and `attempt` is shared with the active state. `append_stage` validates the job and returns canonical dispatchable tool calls. `flush_active_arrivals` validates the active job, appends one finite FIFO snapshot while retaining the round, and returns it. `complete_inference` finishes the round. Call-only stages do not schedule.
`stall_inference` leaves the round open. `restart` makes that round ready under a fresh job without another start and retains its frontier. `halt` is first-write until taken. `recover` validates recognized Chatend conventions, accepts unknown values unchanged, returns idle state with fresh job numbering, and preserves BoxId continuity.
No persistence, KTO, submitted-frontier, actor runtime, provider, Codex, WebSearch, filesystem, or dispatch execution is included.