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
Agent executes your workflow
The orchestrator runs nodes in your graph: LLM calls, conditionals, loops, etc.
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.
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.
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
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.
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.
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
// 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
// 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
// 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.
// 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.
- 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_idcan 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 usingexecute().