Agent execution
What the model is offered on each turn, how each tool call is recorded, and the two ways a turn pauses for a person.
On every turn the runtime offers the model only what the agent declares and what you, the caller, may see or use. That is worked out once per turn, before any toolToolCông cụ (tool)Something an agent can do besides writing text: search knowledge, search the web, read a file, create an artifact, or act in a connected app.Open in glossary is registered, and never cached. Every tool call, pause and resume leaves a row the transcript is rebuilt from.
Key rules
- Offered tools = the agent’s bindings ∩ your access. Narrowing only removes bindings; it never adds one.
- Access is resolved fresh each turn, never cached.
- A turn pauses in exactly two ways: a clarification or an approval.
- Approval precedence: a tool’s own “always ask” setting, then the agent’s setting, then the organisation’s default.
- Run without asking skips the prompt only. Permissions, policy and audit still apply.
What a turn goes through
-
Resolve access for this caller
The agent’s declared bindings are narrowed to what you may use — see Access resolution.
-
Register the surviving tools
Only tools that survived are offered to the model.
-
Call the model
Each block the model emits decides the next step: terminal text ends the turn successfully; a question pauses for your answers; a tool call goes on to the next step.
-
Check whether approval is needed
If not, the tool runs. If so, the turn pauses. Approved, the tool runs; denied, a non-executed tool result is returned instead.
-
Record a trace row and loop
The result — run or not — becomes a trace row, and the loop makes the next model call.
Access resolution
Each kind of binding the agent declares survives only under its own condition:
| Binding | Survives when |
|---|---|
| Model | You may invoke it: a served chat model your department has not blocked. |
| Skill | You can see it and it is published. It is described to the model and loaded by name if the model asks for it during the turn. An unpublished draft is left out. |
| Knowledge | It names a knowledge base in this organisation. Every search narrows again to the bound knowledge bases your own rules reach. |
| Application tool | The bound tool is switched on, its application is active and visible to you, and you have not switched that tool off for yourself in Settings → Connected apps. An application that signs each person in also needs your own active connection, with that tool’s grant enabled. |
- A binding names the organisation’s tool, because an application’s tools belong to the organisation. Only the per-person OAuth kind needs a connection; the other three kinds need none (see Applications and MCP).
- Other binding kinds carry no per-user gate.
- The surviving bindings become tool names, and any tool whose provider the organisation has not configured is dropped.
Visibility rules themselves are explained in Resource visibility.
Always offered
Three tools are offered on every turn and no binding governs them:
- asking you a question (a clarification);
- arithmetic, which reads no data;
- reading back one of this conversation’s earlier tool results, which returns only output the model already received.
The skill loader appears when at least one surviving skill is published and not already folded into the prompt. That way the names the model was given and the names the loader accepts are the same list.
Picking a skill with a slash
You pick a skill by typing / and its name; the composer sends that as the first line of the message. Starting the turn then:
- authorises the slug against what you can see;
- records the selection;
- puts the skill’s instructions into the prompt;
- leaves that skill out of the catalogue the loader offers.
The paragraph above the catalogue tells the model the instructions are already there, so the turn does not spend a call asking for what it is already reading.
Trace rows
Two paths write trace rows into one table, through one ordering counter, so a turn’s trace interleaves them in the order they ran.
| Path | What gets recorded |
|---|---|
| A tool the model calls | A tool-use block, then a tool-result block, on the stream. |
| A runtime callback | The agent calls the backend mid-turn for a capability. On failure, a failed step is recorded with the error. Callbacks that only answer a question — such as issuing the model key — record no step. |
A call an application refuses is raised as an error rather than returned as normal output. That error mark is what draws the row as failed, tells the model its call did not work, and keeps the text out of the check that decides what a claim in the answer is supported by.
How each stream chunk is saved is on Turn lifecycle.
Pauses
A turn pauses for a person in two ways. Both are saved, so a pause survives a refresh.
| Pause | Rule |
|---|---|
| Clarification | One or more questions, each with suggested answers and a free-text option. Answers are saved one per question; the request resolves once every question has one. |
| Approval | A tool call waits for a person to approve or deny it. A replayed pause can never fire twice. A denial returns to the loop as a non-executed tool result. A tool counts as executed only after an explicit execute step, and only if the decision was approval and it has not already run. |
Every clarification answer is checked against the turn first: only the turn’s owner, or someone allowed to read transcripts, can answer. How you answer both kinds of pause is shown in Approvals and questions.
How approval works
Approval gates a tool call the model has already emitted. The model never sees an approval entry in its tool list: the runtime interrupts itself part-way through the call and hands the decision to a person.
The card you answer names the tool, the application behind it and whether it writes — all three read from the request’s own tool record.
Approval decision
Whether a tool call stops for approval depends on three settings, checked in order. The first one set wins:
- The tool’s own setting — an admin can mark a tool Always ask in Admin console → Applications. It then waits for approval even under an agent that normally runs without asking.
- The agent’s override, if the agent sets one.
- The organisation’s default for connected apps.
Each setting is one of two approvalApprovalPhê duyệtYour yes or no before an agent changes something in a connected app. The turn pauses until you decide.Open in glossary modes:
| Mode | What happens |
|---|---|
Ask before each action (ASK_EACH_OPERATION) | The request is saved, the run pauses, and the tool runs only after a person approves. |
| Run without asking (YOLORun without asking (YOLO)Run without asking (YOLO)A connected-app setting that skips the approval prompt for each action. It never bypasses permissions, sign-in scope, policy or the audit log.Open in glossary) | The tool runs with no per-call confirmation. |
How the browser answers a pause and re-attaches to the running turn is on Turn lifecycle.
Turn timing
When a turn ends, each part of the system that handled it — the agent runtime, the backend and the browser — records how long its stages took, in milliseconds, matched across parts by the turn id. Reading them side by side shows where the time went:
- The gap between a model call starting and its request leaving is the before-call hooks, steering among them.
- The gap from the request to the first streamed event is LiteLLM and the model provider.
- A first event well before the first text means the model was reasoning or writing a tool call.
Why it works this way
Why access is resolved per caller, every turn
An agent is shared configuration, but the person invoking it differs. Intersecting the agent’s bindings with the caller’s own access, fresh each turn, means a shared agent can never reach something the caller could not reach directly.
Why approval is an interrupt, not a tool
Approval gates a call the model has already written, so it is not something the model chooses to use. The runtime interrupts itself part-way through the call and hands the decision to a person, which is why approval has its own route and its own table rather than living in the tool list.
Under the hood
Trace row mechanics
Both paths share one atomic ordinal allocator on one table. Finalising a model tool call re-reads the tool-use block’s input and start time from the database. Runtime callbacks use routes guarded by a shared secret, one route per capability, with identity derived from the turn id alone; the wrapper records the failed step and rethrows.
Approval keys and the YOLO decision
An approval is keyed by the runtime’s interrupt id under a unique constraint, so a replayed pause chunk cannot create a second request. The function that decides whether to interrupt takes no auth context and no repository: it is a pure three-input decision, and policy and audit run elsewhere.
Turn timing log lines
| Where | Log line | Figures (ms) |
|---|---|---|
| Runtime | turn timing <id> | Since the invocation arrived: LLM key fetched, tools built, guardrail settings read, agent ready, first answer text leaving the guardrail, answer finished, thinking summary written. Then per model call: SDK start, request sent to LiteLLM, LiteLLM headers, first streamed event, first answer text, end, and the number of requests. |
| Backend, producer | turn timing <id> | Since the browser’s request arrived: turn begun, runtime invoked, first chunk, first text delta in the replay buffer, end. Plus total time persisting chunks and the slowest single write — the next chunk is read only after the previous one is persisted. |
| Backend, reader | turn buffer lag <id> | How long the first text delta and the slowest chunk sat in the replay buffer before this connection wrote them to the browser. Append time comes from Redis’s clock. |
| Browser | turn timing <id> (console, verbose level) | Since send: uploads finished, turn opened, first chunk, first text delta, first frame drawn after it, end. |