惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
WordPress大学
WordPress大学
The Cloudflare Blog
云风的 BLOG
云风的 BLOG
博客园 - Franky
D
Docker
小众软件
小众软件
阮一峰的网络日志
阮一峰的网络日志
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
U
Unit 42
M
MIT News - Artificial intelligence
B
Blog
GbyAI
GbyAI
C
Check Point Blog
P
Proofpoint News Feed
博客园 - 司徒正美
Hugging Face - Blog
Hugging Face - Blog
雷峰网
雷峰网
IT之家
IT之家
Google DeepMind News
Google DeepMind News
V
V2EX
Stack Overflow Blog
Stack Overflow Blog

Workflow SDK Documentation

Patterns for Defining Tools Human-in-the-Loop Building Durable AI Agents Queueing User Messages Resumable Streams Streaming Updates from Tools API Reference Workflow Globals Changelog Resilient run start Cookbook Building a World Deploying Astro Express Fastify Hono Getting Started NestJS Next.js Nitro Nuxt Python SvelteKit Vite corrupted-event-log fetch-in-workflow hook-conflict Errors node-js-module-in-workflow
Sleep, Suspense, and Scheduling
2026-05-31 · via Workflow SDK Documentation

Schedule recurring actions, handle rate limiting, and wait for external state in AI agents.

AI agents sometimes need to pause execution in order to schedule recurring or future actions, wait before retrying an operation (e.g. for rate limiting), or wait for external state to be available.

Workflow SDK's sleep function enables Agents to pause execution without consuming resources, and resume at a specified time, after a specified duration, or in response to an external event. Workflow operation that suspend will survive restarts, new deploys, and infrastructure changes, independent of whether the suspense takes seconds or months.

See the sleep() API Reference for the full list of supported duration formats and detailed API documentation, and see the hooks documentation for more information on how to resume in response to external events.

Sleep is a built-in function in Workflow SDK, so exposing it as a tool is as simple as wrapping it in a tool definition. Learn more about how to define tools in Patterns for Defining Tools.

Define the Tool

Add a new "sleep" tool to the tools defined in workflows/chat/steps/tools.ts:

import { getWritable, sleep } from "workflow"; 

// ... existing imports ...

async function executeSleep( 
  { durationMs }: { durationMs: number }, 
) { 
  // Note: No "use step" here - sleep is a workflow-level function
  await sleep(durationMs); 
  return { message: `Slept for ${durationMs}ms` }; 
}

// ... existing tool functions ...

export const flightBookingTools = {
 // ... existing tool definitions ...
 sleep: { 
  description: "Pause execution for a specified duration", 
  inputSchema: z.object({ 
    durationMs: z.number().describe("Duration to sleep in milliseconds"), 
  }), 
  execute: executeSleep, 
 } 
}

Note that the sleep() function must be called from within a workflow context, not from within a step. This is why executeSleep does not have "use step" - it runs in the workflow context where sleep() is available.

This already makes the full sleep functionality available to the Agent!

Show the tool status in the UI

To round it off, extend the UI to display the tool call status. This can be done either by displaying the tool call information directly, or by emitting custom data parts to the stream (see Streaming Updates from Tools for more details). In this case, since there aren't any fine-grained progress updates to show, we'll just display the tool call information directly:

export default function ChatPage() {

  // ...

  const { stop, messages, sendMessage, status, setMessages } =
    useChat<MyUIMessage>({
      // ... options
    });

  // ...

  return (
    <div className="flex flex-col w-full max-w-2xl pt-12 pb-24 mx-auto stretch">
      // ...

      <Conversation className="mb-10">
        <ConversationContent>
          {messages.map((message, index) => {
            const hasText = message.parts.some((part) => part.type === "text");

            return (
              <div key={message.id}>
                // ...
                <Message from={message.role}>
                  <MessageContent>
                    {message.parts.map((part, partIndex) => {

                      // ...

                      if (
                        part.type === "tool-searchFlights" ||
                        part.type === "tool-checkFlightStatus" ||
                        part.type === "tool-getAirportInfo" ||
                        part.type === "tool-bookFlight" ||
                        part.type === "tool-checkBaggageAllowance"
                        part.type === "tool-sleep"
                      ) {
                        // ...
                      }
                      return null;
                    })}
                  </MessageContent>
                </Message>
              </div>
            );
          })}
        </ConversationContent>
        <ConversationScrollButton />
      </Conversation>

      // ...
    </div>
  );
}

function renderToolOutput(part: any) {
  // ...
  switch (part.type) {
    // ...
    case "tool-sleep": { 
      return ( 
        <div className="space-y-2">
          <p className="text-sm font-medium">Sleeping for {part.input.durationMs}ms...</p>
        </div>
      ); 
    }
    // ...
}

Now, try out the Flight Booking Agent again, and ask it to sleep for 10 seconds before checking any flight. You'll see the agent pause, and the UI reflect the tool call status.

Aside from providing sleep() as a tool, there are other use cases for Agents that commonly call for suspension and resumption.

Rate Limiting

When hitting API rate limits, use RetryableError with a delay:

import { RetryableError } from "workflow";

async function callRateLimitedAPI(endpoint: string) {
  "use step";

  const response = await fetch(endpoint);

  if (response.status === 429) {
    const retryAfter = response.headers.get("Retry-After");
    throw new RetryableError("Rate limited", {
      retryAfter: retryAfter ? parseInt(retryAfter) * 1000 : "1m",
    });
  }

  return response.json();
}