---
name: durable-agent-execution-expert
description: "Expert guide for crash-resilient Durable Agent Execution, Temporal AI workflows, Restate, Cloudflare Workflows, deterministic tool replay, and human-in-the-loop pause/resume sagas / Panduan ahli eksekusi agen AI tahan-gagal (Durable Execution) dengan Temporal, Restate, dan Cloudflare Workflows."
author: "Roedy Rustam"
version: "4.4.2"
---
# Durable Agent Execution & Crash-Resilient Workflow Expert (2026 Edition)
[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
---
## English
### Orchestration & Integration
- **Async Queues & Distributed Sagas**: `async-queue-temporal-expert`, `event-driven-architect`, `error-resilience-expert`
- **AI Agents & Orchestration**: `multi-agent-orchestration`, `ai-llm-integration-expert`, `a2a-agent-protocol-expert`, `agentic-memory-architect`
- **Edge & Serverless Runtimes**: `cloudflare-workers-expert`, `js-backend-expert`
- **Lifecycle & Governance**: `brainstorming`, `zero-to-prod-orchestrator`, `session-memory-manager`
### Description
Production engineering guide for building **crash-proof, long-running AI Agents** using **Durable Execution Engines** (**Temporal.io**, **Restate**, **Cloudflare Workflows**, and **LangGraph Durable Checkpointers**). Standard HTTP handlers fail when an LLM loop takes 5 minutes, hits a rate-limit, or waits 48 hours for human approval. Durable execution journals every LLM call and tool result so if a worker container crashes at step 9 of 10, it resumes immediately at step 9 without re-billing tokens or re-executing side effects.
### Trigger Conditions
- Building autonomous coding, research, or FinTech reconciliation agents that run for minutes, hours, or days.
- Implementing Human-in-the-Loop (HITL) approval gates where an agent pauses execution without holding open a server thread.
- Preventing duplicate LLM token charges or duplicate external API calls when a worker restarts mid-loop.
- Deploying stateful multi-step workflows on Cloudflare Workflows or Restate.
---
### Durable Engine Selection Matrix
| Engine | Runtime Model | State Storage | Best For |
| :--- | :--- | :--- | :--- |
| **Temporal.io** | Long-polling workers (Node/Go/Python/Rust) | Postgres / Cassandra | Complex enterprise sagas, multi-day agent loops |
| **Restate** | Push/RPC Durable Invocations (TS/Rust/Go) | Built-in RocksDB / Raft log | Low-latency microservices, durable idempotency & virtual objects |
| **Cloudflare Workflows** | Serverless Edge (`WorkflowEntrypoint`) | Cloudflare Durable Storage | Zero-infra edge agents, `step.do()` & `step.sleep()` |
| **LangGraph Checkpointer** | Graph State Snapshots | Postgres (`PostgresSaver`) | Conversational time-travel, state branching, thread resume |
---
### Core Implementation Patterns
#### 1. Cloudflare Workflows Durable Agent Loop (`step.do` & `step.waitForEvent`)
Every non-deterministic operation (LLM generation, external tool fetch, `Date.now()`) MUST be wrapped inside a durable `step.do()` block so its return value is persisted in the execution journal:
```typescript
// src/workflows/durable-research-agent.ts
export interface ResearchJobParams {
jobId: string;
tenantId: string;
topic: string;
requireHumanSignoff: boolean;
}
export interface WorkflowStep {
do(name: string, config: { retries?: { limit: number; delay: string; backoff: 'exponential' } }, fn: () => Promise): Promise;
sleep(name: string, duration: string): Promise;
waitForEvent(name: string, options: { type: string; timeout: string }): Promise<{ payload: T }>;
}
export async function runDurableAgentWorkflow(
params: ResearchJobParams,
step: WorkflowStep
) {
// Step 1: Journaled LLM planning call (never re-runs on downstream retry)
const plan = await step.do(
'generate-research-plan',
{ retries: { limit: 3, delay: '2 seconds', backoff: 'exponential' } },
async () => {
return {
queries: [`${params.topic} architecture 2026`, `${params.topic} security invariants`],
estimatedTokens: 4096,
};
}
);
// Step 2: Journaled parallel evidence gathering
const synthesis = await step.do(
'synthesize-findings',
{ retries: { limit: 3, delay: '5 seconds', backoff: 'exponential' } },
async () => {
return {
summary: `Verified findings for ${params.topic}`,
sourcesCount: plan.queries.length,
};
}
);
// Step 3: Zero-compute durable pause for Human-in-the-Loop approval (up to 72 hours)
if (params.requireHumanSignoff) {
const approval = await step.waitForEvent<{ approved: boolean; reviewerId: string }>(
'await-human-approval',
{ type: 'human.approval.submitted', timeout: '72 hours' }
);
if (!approval.payload.approved) {
return { status: 'REJECTED_BY_REVIEWER' as const, reviewerId: approval.payload.reviewerId };
}
}
// Step 4: Commit final output
return await step.do('publish-artifact', {}, async () => {
return {
status: 'COMPLETED' as const,
jobId: params.jobId,
synthesis,
};
});
}
```
---
### Verification Checklist
- [ ] All non-deterministic calls (`fetch`, LLM inference, `crypto.randomUUID()`, `Date.now()`) are executed inside journaled `step.do()` / Activity boundaries.
- [ ] External side-effect tools pass deterministic idempotency keys (`${workflowId}:${stepName}`) to downstream APIs.
- [ ] Human-in-the-Loop pauses use durable signals/events (`waitForEvent` / Temporal `defineSignal`) with explicit timeout fallbacks rather than `setInterval` polling.
- [ ] Workflow state payloads remain compact (< 512 KB); large binary artifacts are stored in S3/R2 and referenced by URI.
---
#### Idempotent Step Checkpoint Executor (TypeScript)
```typescript
export interface StepJournalStore {
getStepOutput(workflowId: string, stepKey: string): Promise;
saveStepOutput(workflowId: string, stepKey: string, output: T): Promise;
}
export async function runDurableStep(
store: StepJournalStore,
workflowId: string,
stepKey: string,
operation: () => Promise
): Promise {
const cached = await store.getStepOutput(workflowId, stepKey);
if (cached !== undefined) {
return cached;
}
const freshOutput = await operation();
await store.saveStepOutput(workflowId, stepKey, freshOutput);
return freshOutput;
}
```
---
#### 3. Temporal.io AI Agent Saga Workflow with Signal Handlers (TypeScript)
Enterprise sagas with multi-day durability and real-time operator overrides:
```typescript
// src/workflows/temporal-agent-saga.ts
export interface AgentSagaInput {
workflowId: string;
tenantId: string;
maxIterations: number;
initialPrompt: string;
}
export interface AgentSignalPayload {
action: 'PAUSE' | 'RESUME' | 'INJECT_CORRECTION' | 'ABORT';
message?: string;
}
export class TemporalAgentWorkflowSaga {
private isPaused = false;
private isAborted = false;
private pendingCorrection: string | null = null;
private currentIteration = 0;
public handleSignal(payload: AgentSignalPayload): void {
if (payload.action === 'PAUSE') {
this.isPaused = true;
} else if (payload.action === 'RESUME') {
this.isPaused = false;
} else if (payload.action === 'ABORT') {
this.isAborted = true;
} else if (payload.action === 'INJECT_CORRECTION' && payload.message) {
this.pendingCorrection = payload.message;
}
}
public async execute(
input: AgentSagaInput,
activities: {
invokeLlmStep: (prompt: string, iteration: number) => Promise<{ nextAction: string; isComplete: boolean }>;
executeToolCall: (action: string) => Promise<{ result: string }>;
publishResult: (workflowId: string, output: string) => Promise;
}
): Promise<{ status: 'COMPLETED' | 'ABORTED'; iterations: number }> {
let currentContext = input.initialPrompt;
while (this.currentIteration < input.maxIterations) {
if (this.isAborted) {
return { status: 'ABORTED', iterations: this.currentIteration };
}
if (this.isPaused) {
// Yield execution without burning CPU or memory
await new Promise((resolve) => setTimeout(resolve, 1000));
continue;
}
if (this.pendingCorrection) {
currentContext += `\n[Operator Correction]: ${this.pendingCorrection}`;
this.pendingCorrection = null;
}
this.currentIteration += 1;
const stepResult = await activities.invokeLlmStep(currentContext, this.currentIteration);
if (stepResult.isComplete) {
await activities.publishResult(input.workflowId, stepResult.nextAction);
return { status: 'COMPLETED', iterations: this.currentIteration };
}
const toolResult = await activities.executeToolCall(stepResult.nextAction);
currentContext += `\n[Tool Output]: ${toolResult.result}`;
}
await activities.publishResult(input.workflowId, currentContext);
return { status: 'COMPLETED', iterations: this.currentIteration };
}
}
```
---
### Sovereign Execution, Token Efficiency & Invariants
| Dimension | Sovereign Mandate & Deterministic Contract |
| :--- | :--- |
| **Frontier Model Cascade** | Medium / High (`GPT-5.6 Sol Medium`, `Gemini 4 Argon`, `Claude Sonnet 5.5 High`, `Grok 4.7 High Fast`) |
| **Availability Fallback** | `Gemini 4 Argon/Pro` -> `Gemini 3.8 Flash`; `Claude Opus 5.5` -> `Claude Opus 4.6` (Zero unhandled missing-model errors) |
| **KV-Cache & Token Protocol** | Pin static instructions & schemas at prompt prefix (`kv-cache-prefix-optimizer`); pass surgical `CONTEXT_MAP.md` slices (<250 tokens/call) during Swarm Fan-Out |
| **SaaT CLI & MCP Dispatch** | CLI: `vibes skill exec durable-agent-execution-expert ` / MCP: `vibes_skill_dispatch`, `vibes_ast_query`, `vibes_compile_cache`, `vibes_optimize_budget`, `vibes_verify_gate` |
| **NFR & Anti-Slop Invariants** | P99 API Gateway Latency < 85ms, OpenAPI 3.1 / TypeSpec strict schema parity, RFC 9457 Problem Details error contracts, Idempotency-Key enforcement; 100% complete zero-placeholder output verified via `node scripts/check-anti-slop.js --strict` |
---
---
## Bahasa Indonesia
### Integrasi Orkestrasi
- **Antrean Asinkron & Saga Terdistribusi**: `async-queue-temporal-expert`, `event-driven-architect`, `error-resilience-expert`
- **Agen AI & Orkestrasi**: `multi-agent-orchestration`, `ai-llm-integration-expert`, `a2a-agent-protocol-expert`, `agentic-memory-architect`
- **Runtime Edge & Serverless**: `cloudflare-workers-expert`, `js-backend-expert`
- **Siklus Hidup & Tata Kelola**: `brainstorming`, `zero-to-prod-orchestrator`, `session-memory-manager`
### Deskripsi
Panduan rekayasa produksi untuk membangun **Agen AI berdurasi panjang yang tahan kegagalan (*crash-resilient*)** menggunakan **Temporal.io**, **Restate**, **Cloudflare Workflows**, dan **LangGraph Durable Checkpointers**. Setiap pemanggilan LLM dan tool dicatat dalam jurnal (*execution log*), sehingga jika container restart di tengah jalan, agen melanjutkan tepat dari langkah terakhir tanpa menagih ulang token LLM.
### Panduan Arsitektur Inti
1. **Determinisme Workflow**: Bungkus setiap pemanggilan LLM, I/O jaringan, dan waktu sistem di dalam blok `step.do()` atau *Activity* agar hasilnya disimpan di jurnal.
2. **Human-in-the-Loop Tanpa Biaya Compute**: Gunakan `step.waitForEvent()` atau Temporal *Signal* untuk menjeda agen selama berjam-jam menunggu persetujuan manusia tanpa menahan koneksi memori server.
3. **Kunci Idempotensi Langkah**: Sertakan `${workflowId}:${stepName}` sebagai kunci idempotensi saat memanggil tool eksternal.
### Daftar Periksa Verifikasi (Checklist)
- [ ] Seluruh pemanggilan LLM dan I/O dibungkus dalam *durable step/activity*.
- [ ] Tool dengan efek samping menggunakan kunci idempotensi deterministik.
- [ ] Jeda *human-in-the-loop* memiliki batas waktu (*timeout*) eksplisit.
### Matriks Eksekusi Berdaulat, Efisiensi Token & Invarian
| Dimensi | Mandat Berdaulat & Kontrak Deterministik |
| :--- | :--- |
| **Kaskade Model Frontier** | Medium / High (`GPT-5.6 Sol Medium`, `Gemini 4 Argon`, `Claude Sonnet 5.5 High`, `Grok 4.7 High Fast`) |
| **Invarian Fallback Ketersediaan** | `Gemini 4 Argon/Pro` -> `Gemini 3.8 Flash`; `Claude Opus 5.5` -> `Claude Opus 4.6` (Bebas gagal saat model belum tersedia/kuota penuh) |
| **Protokol Hemat Token & KV-Cache** | Kunci instruksi & skema statis di prefix awal (`kv-cache-prefix-optimizer`); kirim potongan `CONTEXT_MAP.md` (<250 token/panggilan) saat Fan-Out |
| **Eksekusi SaaT CLI & MCP** | CLI: `vibes skill exec durable-agent-execution-expert ` / MCP: `vibes_skill_dispatch`, `vibes_ast_query`, `vibes_compile_cache`, `vibes_optimize_budget`, `vibes_verify_gate` |
| **Invarian NFR & Anti-Slop** | Latensi P99 API < 85ms, paritas skema ketat OpenAPI 3.1 / TypeSpec, kontrak error RFC 9457 Problem Details, penegakan Idempotency-Key; kode 100% tuntas tanpa placeholder diverifikasi melalui `node scripts/check-anti-slop.js --strict` |