Skip to main content

Concepts

All Concepts pages in the AgentOS documentation.

📄️The Turn Lifecycle

One request to the full runtime becomes one GMI turn. Five stages own it, in this order; every line names the code that runs it. When the model requests a tool the host executes, processRequest() yields that chunk and returns; the host continues the same turn through handleToolResult(), handleToolResults() or, with the pending request stored on the conversation (getPendingExternalToolRequest()), resumeExternalToolRequest(). The streams those calls return pass through the same output guardrails as the turn's stream. A turn stops for the host only when the GMI's output is not final (isFinal the runtime ends the turn or the continuation with FINALRESPONSE, which lists them in finalToolCalls, and saves no pending request for them. Every output that does not stop for the host ends the turn or the continuation, marked final or not, with one FINALRESPONSE that both build the same way (turnFinalResponse.ts) SYSINVALIDSTATE while the stream is open (its pause is being continued, or the stream's next pause replaced it), and TOOLERROR once the stream is closed (its turn or continuation ended, a resume took the pause, a newer turn ended it, or an output guardrail blocked it). A resume ends the stream the pause was saved on. A call of the pause that the results leave out is answered with a tool result that says it has none (code EXTERNALTOOLNOTRUN), after the results the host passed and before the GMI writes again each call of the pause is answered the same way, right after the pause's assistant message, the pending request is cleared, and the pause's stream is closed. A turn the runtime refuses before then (an organization a strict single-tenant runtime refuses, or a turn plan that fails) leaves the pause as it was. With enableConversationalPersistence off the runtime records no message of a pause in the conversation, neither its call nor a refusal, and a resume continues on the GMI's own history the GMI the turn paused on keeps its own history while that history holds no turn of another conversation, since it also holds the calls the GMI ran itself in the turn; otherwise the runtime sets the GMI's history, and its session, conversation and organization from the pause's stream, before the conversation records the results; a GMI whose last turn was another conversation's then also drops what it kept for that turn (its memory scope, tool-call gate, learning preparation and model hop), so the continuation starts as on a GMI built for it and asks the learning layer for a preparation of its own. The continuation's calls are judged with the tool-call gate it is given, or else with the one its turn ran with, which the runtime keeps with the turn's stream (AgentOSOrchestrator.orchestrateToolResult() takes none). The history it sets is the GMI's own history of the paused turn when the runtime kept one, which a turn that stops for the host leaves with the turn's stream an acquisition for a session whose GMI it deactivates (a persona refresh, cleanupInactiveGMIs()) waits until that GMI has shut down and then gets a new one. A conversation that holds no history of the paused turn (persistence off) cannot continue on another GMI, so the results are refused with an error and the pause stays. With persistence off the GMI's own history is the only record of the session's conversations, so a continuation on a GMI that ran a turn of another conversation reads that turn too, as each turn of the session reads the others getPendingExternalToolRequest() returns it, a resume continues it, and a new turn ends it. A continuation that fails after the conversation recorded its results keeps them. A pause that a turn or a continuation saved before it failed (the store refuses that save) ends the way a new turn ends one, since the host never read its request. AgentOS does not queue a conversation's operations the host reads it only when it is the one such request the GMI streamed and names exactly the calls the turn stops for, and otherwise reads a request the runtime builds for them; a turn that does not stop for the host streams none of them, so the host reads on to the reply. A request for calls the GMI runs itself (executionMode: 'internal') streams as it comes, and the stream never carries a request that names no call, which would give the host nothing to run.