Tool Calls Interrupted? APX's Explicit End Marker

Interrupted tool calls must have an explicit ending in the conversation history to prevent the model from fabricating results.
The article notes that AI Agent tool calls are often interrupted by crashes, timeouts, or user stops, leaving dangling calls with only a request and no result. This half-finished state causes the next turn to inherit ambiguous semantics, inducing the model to fabricate results that never happened and even to continue reasoning based on incomplete actions or misjudge side effects. When repairing chat history, APX follows a strict sequencing rule and appends a "not run: the turn was interrupted" record to every unanswered call. It only states that no tool result was received, without claiming the external action failed, thereby preserving room for safe retries. The article further distinguishes portable project context (APC) from local execution state (APX): the former provides persistent intent, while the latter preserves honest operational facts. During recovery, three questions should be answered separately: whether a tool was requested, whether a result was received, and what check is safe.
Why Interrupted Tool Calls Need an Explicit Ending
An AI Agent may "drop the turn" while calling a tool before getting a result—the browser crashes, the provider times out, the runtime restarts, or the user stops it. Such interruptions are normal, but pretending they never happened is not. When repairing chat history, APX follows a simple rule: an interrupted tool call must have an explicit ending in the conversation history. It does not leave a dangling request; instead, it records "the tool did not run because the turn was interrupted."

This rule may seem minor, but it directly addresses the structural requirement of tool-calling APIs: strict sequencing. When an assistant message requests a tool, a corresponding tool result must follow immediately. If the history contains only a request with no result, the next turn inherits an ambiguous state—did the browser search actually happen? Was the file written? Is it safe to retry? The model should not have to guess, and later readers should not infer "the action succeeded" from an assistant message that "requested an action."
The "strict sequencing" requirement of tool-calling APIs stems from the design constraints of modern large-model function calling protocols: conversation messages are divided into roles such as assistant (which may carry tool_calls) and tool (which carries tool_call_id and the result). When parsing history, servers typically require that every tool_call be followed by a tool message with a matching id; otherwise, they return a 400 error or behavior is undefined. This constraint is not a proprietary implementation of any single vendor but a shared specification of mainstream interfaces such as OpenAI Chat Completions and Anthropic Messages. Its purpose is to let the model understand "requesting an action" and "the action's result" as an indivisible atomic unit. When only half a call remains in the history, the model does not see "unknown" but a syntactically incomplete action that semantically looks like it already happened—this is precisely the source of hallucination risk.
The Real Risks of Dangling Calls
Consider a very short conversation history:
User: Check the deployment dashboard.
Assistant: Calling browser_text({ url: ... })
[process interrupted]
User: What did it find?
Without repair, the last question invites the model to fabricate. A plausible-sounding answer might convincingly summarize the dashboard even though no result ever existed. This is worse than a visible interruption because it turns missing evidence into an assertion.
The "half-finished" state of a tool call also contaminates subsequent reasoning. The model may continue planning based on an action that was never completed, or incorrectly believe that a side effect has occurred. In scenarios requiring idempotency or side effects, this confusion can lead to duplicate writes or missed checks.
"Idempotency" means that performing the same operation once or multiple times produces the same effect on system state. Read-only operations such as reading a dashboard or querying task status are naturally idempotent, and repeated execution has no side effects; operations such as writing files, sending messages, creating orders, or deducting inventory are non-idempotent, and repeated execution may cause duplicate writes or duplicate charges. This is exactly what makes interrupted calls most tricky: from the history alone, it is impossible to determine whether a side effect has already occurred. A sound recovery strategy is to prioritize idempotent checks (for example, query the resource's current state before deciding whether to write) or to introduce an idempotency key so that the external service can deduplicate on its own, rather than retrying blindly. This is also why the article emphasizes that the "not run" record only states that no result was received and does not claim external failure—it returns the responsibility for judging whether a side effect occurred to the caller instead of drawing conclusions on the caller's behalf.
How APX Repairs Structure, Not the Story
APX's runtime history repair logic starts from real user entries, ignores orphaned tool results, and checks whether each assistant tool call has a matching result. When a new non-tool entry appears or the history ends, any unanswered call is closed with an explicit record:
not run: the turn was interrupted
The repaired history becomes:
User: Check the deployment dashboard.
Assistant: Calling browser_text({ url: ... })
Tool: not run: the turn was interrupted
User: What did it find?
This record is deliberately narrow. It does not claim that the action failed in the external world—the request may have reached the external service before the runtime lost contact. It only states that APX has no completed tool result for that turn. This distinction is crucial for retries: the safe next step may be to check the current state, ask the user, or run an idempotent check, rather than automatically "doing it again."
The Boundary Between Portable Context and Runtime State
This repair is runtime work, not a modification to project context. APC maintains the portable contract: AGENTS.md in the repository, .apc/ metadata, Agent definitions, skills, and safe shared guidance. Compatible tools can read this contract from another checkout.
APX is the runtime used day to day. Its chat history, tool-call records, sessions, and interruption markers are local execution state. They must describe what happened in a specific conversation, but they are not part of the portable project contract.
This boundary makes recovery easier to reason about. APC still tells the Agent which project rules and skills apply after a restart; APX separately tells it whether the last tool call produced evidence. One layer provides persistent intent, and the other preserves honest operational facts.
The separation of portable context and local runtime state is essentially the separation of "declarative configuration" and "imperative execution records." The former describes what rules the system should be under (project conventions, Agent definitions, available skills) and can be versioned with the repository and reused across machines; the latter describes what actually happened in a particular execution (message sequence, tool calls, interruption markers) and is session-local and time-sensitive. Mixing execution state into the portable contract would cause the contract to drift with every run, making it impossible for other checkouts to reproduce; conversely, stuffing project rules into runtime state would lose intent after a restart. Each layer has different responsibilities, so during recovery they can separately answer the two orthogonal questions: "which rules currently apply" and "did the last action actually succeed?"
Practical Recovery Habits
When a tool-dependent turn is interrupted, separate three questions:
- Was a tool requested?
- Did APX receive a matching result?
- What check is safe before continuing?
Only the second question has a definitive answer from the repaired history. The third depends on the operation itself: check a read-only dashboard, inspect task status, or ask before repeating a write.
An explicit interruption marker is unremarkable, but it prevents a subtle class of Agent errors. APC keeps project context portable, and APX keeps execution history accountable. The next turn can then continue based on evidence rather than from a gap that looks like success.
Related articles

Random Pruning of the DPO Computation Graph: 1.4x Training Speedup and Lower Peak Memory
DPO training too slow and memory-hungry? This paper proposes a random pruning framework for the DPO computation graph, sampling independently across position, sequence, and branch dimensions; branch pruning achieves a 1.426x step-time speedup and cuts training time by about 30%, with in-depth attribution of memory and time gains.

Why Does JEPA Underperform MLM in Longitudinal EHR Representation Learning?
New study compares JEPA and MLM for longitudinal EHR representation learning on MIMIC-IV: three JEPA variants train stably without collapse but underperform MLM; target size, not heterogeneity, drives prediction error.

Transfer Learning + Visible Light Communication: A New Approach to Energy-Efficient Indoor Positioning
A study proposes a transfer learning-based visible light communication indoor positioning method, achieving 47% accuracy improvement on the BOSCH factory dataset, 67.5% model efficiency under high noise, and introducing the ME composite metric for energy-efficient positioning in energy-constrained industrial IoT scenarios.