World and request ownership
One session per visit
Register WorldLifecycle once from your module root. Its returned WorldBinding resolves a tool call to the session for that call. Opening and reconnecting an AI conversation do not create another game session. Dimension travel calls relocated; it keeps the same session.
open, tick, relocated and the beginning of close run on the client thread. Do not block on files, networking or server-owned data there. A session returned by open owns its asynchronous loading and retirement. If open throws before returning, it must release its allocations itself.
On world exit the host closes admission before calling close. Return actual persistence/resource completion, not acknowledgement. Completion must not require another tick. An old visit can still be saving while the next one opens: keep their state separate and serialize conflicting file operations. Shared worker shutdown belongs in WorldLifecycle.shutdown.
One context per call
Use CallContext.onClient for small client actions after asynchronous work. The host rechecks request, task and visit lifetimes before executing them. Reading isActive and later acting on another thread is not an atomic permission check. Server access requires the server's own execution rules.
Capture the original session and immutable input before I/O. Never apply an old result through WorldBinding.current() to whichever world happens to be open. ended() lets an observer stop waiting; producers still own accepted I/O and native cleanup.
All queries belong to the observed location revision. Tools may choose WORLD to survive dimension travel or LOCATION to require the exact location. Neither scope keeps a request alive after world exit.
Replay and results
TASK_OPERATION groups the same tool, task, scope and operation ID. Identical calls share execution; changed parameters conflict. Failures are retained too. A timeout does not prove that an effect was rolled back, so inspect domain state before deliberately starting a new operation ID. This is not durable exactly-once execution across reconnections.
Commit state before emitting callbacks or starting effects. On rejection, cancellation or late completion, identify who owns cleanup and what accepted work proceeds next. A stale-result check alone is not a progress guarantee.
inputContext captures small observations for one input. It is not an instruction channel or a live subscription. Return an empty Optional when there is no reference; the host does not reuse the previous value.