# How OpenMAIC Ensures Tool Integrity in the Agent Runtime: A Technical Deep Dive

> OpenMAIC ensures tool integrity at agent runtime using orphan detection, interrupted result synthesis, and contiguity repair for reliable LLM interactions. Discover the technical details.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: deep-dive
- Published: 2026-09-06

---

**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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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.

```typescript
// 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:

```typescript
// 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.

```typescript
// 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:

```typescript
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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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:

```typescript
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:

```typescript
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:

1. **After** custom context transforms modify the message history
2. **Before** conversion to the provider-specific format
3. **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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/agent-runtime/tool-call-integrity.test.ts): Direct coverage of orphan detection, repair logic, and interrupted result generation
- [`tests/lib/agent/runtime/tool-timeout.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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.