Skip to main content
This guide takes you through building your first AI agent with Restate and popular AI SDKs. We will run a simple weather agent that can answer questions about the weather using durable execution to ensure reliability. AI Agent Quickstart

Building with an AI coding agent?

Every Restate template ships with the Restate coding agent plugin pre-configured. Your agent gets Restate expertise plus access to the full docs via MCP. Useful for:
  • Migrating an existing application to Restate
  • Building a new Restate service from scratch
Select your AI SDK:
Prerequisites:
1

Install Restate Server & CLI

Restate is a single self-contained binary. No external dependencies needed.
brew install restatedev/tap/restate-server restatedev/tap/restate
Start the server:
restate-server
You can find the Restate UI running on port 9070 (http://localhost:9070) after starting the Restate Server.
2

Get the AI Agent template

Get the weather agent template for the Vercel AI SDK and Restate:
restate example typescript-vercel-ai-template && cd typescript-vercel-ai-template
npm install
3

Run the AI Agent service

Export your OpenAI key and run the agent:
export OPENAI_API_KEY=your_openai_api_key_here
npm run dev
The weather agent is now listening on port 9080.
4

Register the service

Tell Restate where the service is running (http://localhost:9080), so Restate can discover and register the services and handlers behind this endpoint. You can do this via the UI (http://localhost:9070):
Restate UI Playground
If you run Restate with Docker, register http://host.docker.internal:9080 instead of http://localhost:9080.
When using Restate Cloud, your service must be accessible over the public internet so Restate can invoke it. If you want to develop with a local service, you can expose it using our tunnel feature.
5

Send weather requests to the AI Agent

Invoke the agent via the Restate UI playground: go to http://localhost:9070, click on your service and then on playground.
Restate UI Playground
Or invoke via curl:
curl localhost:8080/restate/call/agent/run --json '{"prompt": "What is the weather in San Francisco?"}'
Output: The weather in San Francisco is currently 23°C and sunny..
6

Congratulations, you just ran a Durable AI Agent!

The agent you just invoked uses Durable Execution to make agents resilient to failures. Restate persisted all LLM calls and tool execution steps, so if anything fails, the agent can resume exactly where it left off.We did this by using Restate’s durableCalls middleware to persist LLM responses and using Restate Context actions (e.g. ctx.run) to make the tool executions resilient:
import * as restate from "@restatedev/restate-sdk";
import { durableCalls } from "@restatedev/vercel-ai-middleware";
import { openai } from "@ai-sdk/openai";
import { generateText, stepCountIs, tool, wrapLanguageModel } from "ai";
import { z } from "zod";

// TOOL
async function getWeather(ctx: restate.Context, city: string) {
  // Do durable steps using the Restate context
  return ctx.run(`get weather ${city}`, () => {
    // Simulate calling the weather API
    return {temperature: 23, description: `Sunny and warm.`}
  })
}

// AGENT
const run = async (ctx: restate.Context, { prompt }: { prompt: string }) => {
  const model = wrapLanguageModel({
    model: openai("gpt-5.4"),
    // Persist LLM responses
    middleware: durableCalls(ctx, { maxRetryAttempts: 3 }),
  });

  const { text } = await generateText({
    model,
    system: "You are a helpful agent that provides weather updates.",
    prompt,
    tools: {
      getWeather: tool({
        description: "Get the current weather for a given city.",
        inputSchema: z.object({ city: z.string() }),
        execute: async ({ city }) => getWeather(ctx, city),
      }),
    },
    stopWhen: [stepCountIs(5)],
    providerOptions: { openai: { parallelToolCalls: false } },
  });

  return text;
};

// AGENT SERVICE
const agent = restate.service({
  name: "agent",
  handlers: {
    run: restate.createServiceHandler({
      input: restate.serde.schema(z.object({
        prompt: z.string().default("What's the weather in San Francisco?"),
      })),
    }, run),
  },
});

restate.serve({ services: [agent] });
The Invocations tab of the Restate UI shows us how Restate captured each LLM call and tool step in a journal:
Restate UI Journal Entries
Let the weather tool raise an error by adding the following line to the get_weather function:
throw new Error(`[👻 SIMULATED] "Fetching weather failed: Weather API down..."`);
You can see in the Restate UI how each LLM call and tool step gets durably executed. We can see how the weather tool is currently stuck, because the weather API is down.
Restate UI Durable Execution
Fix the problem, by removing the error again.Once you restart the service, the agent resumes at the weather tool call and successfully completes the request.
Restate UI Durable Execution
Next step: Learn more about Durable Agents and how Restate makes your AI agents resilient to failures.