Skip to main content
Guides

Workflow Checkpoints & Resume

When an agent workflow pauses — for an external tool call or a human approval — Agentlify saves the full execution state server-side. You resume with a single resume_id, no need to re-send messages or context.

Zero-effort resumption

Every paused response includes a resume_id. To continue, just pass the resume_id plus your payload (tool results or approval decision). The server restores the exact graph state — node position, variable values, conversation history — and picks up where it left off.

How It Works

1

Agent executes your workflow

The orchestrator runs nodes in your graph: LLM calls, conditionals, loops, etc.

2

Workflow pauses

When the agent hits an external tool call or a human approval node, execution pauses. The full graph state is serialized and saved to a checkpoint.

3

Response includes resume_id

The API response includes a resume_id alongside the pending tool calls or approval request. The checkpoint stores everything: graph position, state variables, conversation history, and tool definitions.

4

You resume with one call

Send the resume_id + your payload (tool results or approval decision). The orchestrator restores the checkpoint and continues from the exact node where it paused.

What Causes a Pause

External Tool Calls

When an LLM node calls a tool that is configured for client-side execution (no webhook URL), the orchestrator pauses and returns the tool calls. You execute the tool in your code and send the results back.

The response has finish_reason: "tool_calls" and a resume_id.

Human Approval Nodes

When the workflow reaches a User Approval node, it pauses and returns the approval request. A human reviews and decides: approved, rejected, or timed out.

The response has status: "approval_required" and a resume_id.

Automatic Resumption (Agentlify SDK)

If you use the Agentlify JS SDK with tool callbacks, the SDK handles checkpoints automatically. You don't need to think about resume_id at all — the SDK executes your callbacks and resumes the agent behind the scenes.

javascript
const Agentlify = require('agentlify-js');

const client = new Agentlify({
  apiKey: process.env.AGENTLIFY_API_KEY,
  routerId: process.env.AGENTLIFY_ROUTER_ID
});

// The SDK handles the full checkpoint/resume loop automatically
const response = await client.agents.run({
  agentId: 'my-agent',
  messages: [{ role: 'user', content: 'What is the weather in NYC?' }],
  tools: [{
    type: 'function',
    function: {
      name: 'get_weather',
      description: 'Get current weather for a location',
      parameters: {
        type: 'object',
        properties: { location: { type: 'string' } },
        required: ['location']
      }
    },
    // Your callback runs locally — the SDK resumes the agent with the result
    callback: async ({ location }) => {
      const res = await fetch(`https://api.weather.com/${location}`);
      return await res.json();
    }
  }],
  // Optional: observe each tool iteration
  onToolIteration: ({ iteration, toolCalls, resumeId }) => {
    console.log(`Tool iteration ${iteration}, resume_id: ${resumeId}`);
  }
});

// Final response — all tool calls were handled automatically
console.log(response.choices[0].message.content);

Manual Resume: Tool Calls

If you use client.agents.execute() or the raw HTTP API, you handle the checkpoint loop yourself.

Step 1: Detect the pause

javascript
// Using the Agentlify SDK (execute = no auto-resume)
const response = await client.agents.execute({
  agentId: 'my-agent',
  messages: [{ role: 'user', content: 'Look up order #12345' }],
  tools: [{ type: 'function', function: { name: 'lookup_order', ... } }]
});

if (response.choices[0].finish_reason === 'tool_calls') {
  const resumeId = response.resume_id;
  const toolCalls = response.choices[0].message.tool_calls;
  // Execute your tools...
}

Step 2: Resume with results

javascript
// Execute your tool locally
const orderData = await lookupOrder(toolCalls[0].function.arguments);

// Resume the agent — just the resume_id + tool results
const resumed = await client.agents.resume({
  resumeId: resumeId,
  toolResults: [{
    toolCallId: toolCalls[0].id,
    output: JSON.stringify(orderData)
  }]
});

// Check if the resumed execution completed or paused again
if (resumed.next_resume_id) {
  // Agent paused again — handle the next pause
  console.log('Next resume ID:', resumed.next_resume_id);
} else {
  console.log('Final output:', resumed.output);
}

Manual Resume: Approvals

javascript
// The agent paused for approval
// response.status === 'approval_required'
// response.resume_id === 'abc-123'

// After the human reviews and decides:
const resumed = await client.agents.resume({
  resumeId: 'abc-123',
  decision: 'approved',   // 'approved' | 'rejected' | 'timed_out'
  reason: 'Looks good'    // Optional (required for rejections)
});

console.log('Resumed output:', resumed.output);

Raw HTTP API

If you're not using the Agentlify SDK, you can call the resume endpoint directly via HTTP.

bash
// Resume a tool call pause
curl -X POST https://agentlify.co/api/agents/resume \
  -H "Authorization: Bearer mp_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "resumeId": "abc-123-def-456",
    "toolResults": [
      { "toolCallId": "tc_001", "output": "{\"status\": \"shipped\"}" }
    ]
  }'

// Resume an approval pause
curl -X POST https://agentlify.co/api/agents/resume \
  -H "Authorization: Bearer mp_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "resumeId": "abc-123-def-456",
    "decision": "approved",
    "reason": "Verified by manager"
  }'

Chaining: Multiple Pauses

A workflow can pause multiple times. Each time you resume, the response may include a new next_resume_id if the workflow pauses again. This supports complex workflows like:

Tool call → you provide results → Approval node → human approves → Another tool call → you provide results → Workflow completes

Each pause produces a new checkpoint. The client.agents.run() method in the SDK handles tool call chains automatically. For approval nodes, the SDK returns immediately so you can present the approval request to the user.

What Gets Saved in a Checkpoint
  • Current node position in the workflow graph
  • All state variables ({{state.key}} values)
  • Output of every node executed so far
  • Full conversation message history
  • Tool definitions
  • Agent configuration and ID
  • Pending tool calls or approval request details

Important Notes

  • Each resume_id can only be used once. After resuming, the checkpoint is marked as resolved.
  • Checkpoints are scoped to the authenticated user — you cannot resume another user's checkpoint.
  • The client.agents.run() method handles tool call checkpoints automatically. You only need manual resume for approval nodes or if using execute().