How OpenMAIC Ensures Tool Integrity in the Agent Runtime: A Technical Deep Dive
OpenMAIC protects tool-call integrity through orphan detection, interrupted result synthesis, and contiguity repair, ensuring every tool call has a matching result before reaching the LLM provider.
The agent runtime in OpenMAIC—maintained by THU-MAIC—faces a critical challenge: maintaining consistent tool-call state across asynchronous execution, network interruptions, and storage lease losses. Without rigorous safeguards, partial tool executions could corrupt the conversation transcript and violate provider invariants. The lib/server/agent-runtime/tool-call-integrity.ts module implements a read-time integrity guard that detects, repairs, and synthesizes missing tool-call results before the model ever sees them.
Core Mechanisms for Tool Integrity
OpenMAIC's tool-call integrity system operates through six tightly-coupled mechanisms. Each targets a specific failure mode in distributed agent execution.
Orphan Detection via orphanedToolCalls
The runtime first identifies tool calls that lack corresponding results. The orphanedToolCalls function scans the entire message transcript, builds a set of tool-call IDs, and returns any unmatched calls as PendingToolCall objects.
// lib/server/agent-runtime/tool-call-integrity.ts#L76-L90
function orphanedToolCalls(messages: AgentMessage[]): PendingToolCall[] {
const callIds = new Set<string>();
const resultIds = new Set<string>();
for (const msg of messages) {
if (msg.role === 'assistant' && msg.tool_calls) {
msg.tool_calls.forEach(tc => callIds.add(tc.id));
} else if (msg.role === 'tool') {
resultIds.add(msg.tool_call_id);
}
}
return [...callIds]
.filter(id => !resultIds.has(id))
.map(id => ({ tool_call_id: id, status: 'pending' }));
}
This detection runs automatically during the repair phase, ensuring no orphaned calls escape notice.
Interrupted Result Synthesis
When a tool call aborts before completion—due to timeout, cancellation, or lease loss—the runtime must still produce a valid result. The interruptedToolResult function generates a deterministic error payload:
// lib/server/agent-runtime/tool-call-integrity.ts#L64-L73
function interruptedToolResult(toolCallId: string): ToolMessage {
return {
role: 'tool',
tool_call_id: toolCallId,
content: JSON.stringify({ ok: false, error: 'interrupted' }),
};
}
This synthesis preserves the provider invariant that every tool call has exactly one result, even for failed or abandoned operations.
Contiguity Repair with repairOrphanedToolCalls
The most complex mechanism rebuilds malformed transcripts. The repairOrphanedToolCalls function (lines 92-182) enforces three critical properties:
- Contiguity: All results for an assistant's tool calls appear immediately after that assistant message
- Ordering: Results match the order of calls in the original request
- Completeness: No call lacks a result
The repair process drops duplicated results, removes aborted assistant frames with no surviving results, and inserts synthesized interrupted results where needed. As noted in the source comments (lines 99-106), this repair executes right before model conversion, leaving the durable storage as an immutable audit trail while ensuring the model-facing view is always legal.
// Example: Manual transcript repair
import { repairOrphanedToolCalls } from '@/lib/server/agent-runtime/tool-call-integrity';
const rawMessages: AgentMessage[] = /* persisted transcript with gaps */;
const { messages: repaired, repairedToolCalls } = repairOrphanedToolCalls(rawMessages);
console.log(`Fixed ${repairedToolCalls.length} orphaned calls`);
Higher-Order Wrapper: withToolCallIntegrityRepair
OpenMAIC exposes a composable wrapper that automatically applies integrity repair to any context transform. This pattern (lines 95-100) ensures repair happens consistently without polluting business logic:
import { withToolCallIntegrityRepair } from '@/lib/server/agent-runtime/tool-call-integrity';
async function myTransform(messages: AgentMessage[]): Promise<AgentMessage[]> {
// Custom reordering, filtering, or augmentation
return messages.filter(m => !isSpam(m));
}
// Integrity repair now runs automatically on every turn
export const safeTransform = withToolCallIntegrityRepair(myTransform);
The wrapper integrates seamlessly with the runtime pipeline defined in lib/server/agent-runtime/runner.ts, where the main execution loop applies context transforms before model invocation.
In-Flight Tracking via trackToolCallMessage
During active sessions, the runtime maintains a map of pending calls using trackToolCallMessage (lines 202-212). This function updates an in-memory Map<string, PendingToolCall> as messages flow through the system:
const inflight = new Map<string, PendingToolCall>();
function onMessage(message: AgentMessage) {
trackToolCallMessage(inflight, message);
// Automatically adds tool calls, removes entries on matching results
}
This tracking enables precise identification of calls that were in progress when a session aborts.
Safe Append on Lease Loss
The appendInterruptedToolCallResults function (lines 120-136) handles the critical edge case of storage lease expiration. Rather than throwing generic errors, it invokes a user-supplied onFenceLost callback for graceful degradation:
await appendInterruptedToolCallResults(
[...inflight.values()], // Pending calls from tracking map
{
append: async (msg) => storage.append(msg),
onFenceLost: () => {
logger.warn('Storage lease lost - aborting graceful append');
// Application-defined recovery: notify user, checkpoint state, etc.
},
},
);
This mechanism prevents partial writes and gives applications control over failure recovery.
Runtime Integration and Execution Flow
OpenMAIC's integrity layer sits at a precise architectural boundary. The repair executes:
- After custom context transforms modify the message history
- Before conversion to the provider-specific format
- Without mutating the durable storage layer
This design upholds auditability—stored transcripts record exactly what happened—while guaranteeing that models receive only valid, complete sequences.
The runner.ts file wires these pieces together, invoking withToolCallIntegrityRepair on the active transform and feeding the repaired context into the LLM provider client.
Testing and Verification
The integrity mechanisms are exercised by dedicated test suites:
tests/agent-runtime/tool-call-integrity.test.ts: Direct coverage of orphan detection, repair logic, and interrupted result generationtests/lib/agent/runtime/tool-timeout.test.ts: Indirect verification through simulation of global execution bounds and aborted frames
These tests validate edge cases including out-of-order results, duplicated result messages, and mid-transaction lease losses.
Summary
OpenMAIC ensures tool integrity in the agent runtime through:
- Orphan detection that identifies unmatched tool-call IDs across the transcript
- Deterministic synthesis of interrupted results for aborted or timed-out calls
- Contiguity repair that rebuilds transcripts to satisfy provider invariants
- Composable wrappers that guarantee repair runs on every context transformation
- In-flight tracking for precise identification of pending operations
- Graceful lease-loss handling via callbacks rather than uncontrolled exceptions
The system guarantees every tool call has a corresponding result, results appear contiguously and in order, and interrupted frames cannot corrupt the conversation state—all without sacrificing auditability of the underlying storage.
Frequently Asked Questions
What happens if a tool call times out before producing a result?
OpenMAIC's interruptedToolResult function synthesizes a deterministic error payload with {ok: false, error: "interrupted"}. This synthesized result is inserted during the repair phase, preserving the provider invariant that every call has exactly one result. The original assistant frame may be dropped if no real results survive, preventing partial corruption.
Where does the integrity repair run in the OpenMAIC pipeline?
According to source comments in repairOrphanedToolCalls (lines 99-106), repair executes immediately before model conversion. This placement ensures the durable storage remains an immutable audit trail while the model-facing view is always valid. The withToolCallIntegrityRepair wrapper in runner.ts automates this placement for all context transforms.
Can applications customize behavior when storage leases are lost?
Yes. The appendInterruptedToolCallResults function accepts an onFenceLost callback in its options parameter. When the storage lease (attempt fence) expires, this callback fires instead of propagating a generic error. Applications can implement custom recovery: logging, user notification, state checkpointing, or alternative persistence strategies.
How does OpenMAIC handle historically corrupted transcripts?
The repairOrphanedToolCalls function can run on-demand against any message array. Applications may invoke it during migrations, replay scenarios, or debugging sessions to clean up transcripts that predate integrity safeguards. The function returns both the repaired messages and a list of specific repairs applied, enabling transparent audit of historical fixes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →