### Example Project Setup Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/tour-of-agents/README.md Commands to get the example project and install its dependencies. ```bash restate example typescript-vercel-ai-tour-of-agents && cd typescript-vercel-ai-tour-of-agents npm install ``` -------------------------------- ### Run example Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/examples/README.md To get started, cd into any of the examples and then run them. ```shell uv run . ``` -------------------------------- ### Starting the Agents NextJS app Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-example-app/README.md Commands to install dependencies and run the NextJS development server. ```bash npm install npm run dev ``` -------------------------------- ### Install Restate Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/langfuse/README.md Install Restate via brew or other installation methods. ```bash brew install restatedev/tap/restate-server restatedev/tap/restate ``` -------------------------------- ### Starting Restate Server Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-example-app/README.md Command to start the Restate server. ```shell npx @restatedev/restate-server@latest ``` -------------------------------- ### Start the agent service Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/langfuse/README.md Start the agent service using uvicorn. ```bash uv run --env-file .env . ``` -------------------------------- ### Start NextJS App Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-template/README.md Starts the NextJS application which includes the agent code. ```shell npm run dev ``` -------------------------------- ### Download the example Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/examples/langfuse/README.md Commands to download the example project and navigate to the Langfuse directory. ```bash restate example python-google-adk-examples cd python-google-adk-examples/langfuse ``` -------------------------------- ### Download the example Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/langfuse/README.md Download the example code for the Langfuse integration. ```bash restate example python-openai-agents-examples cd python-openai-agents-examples/langfuse ``` -------------------------------- ### Download Example Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/arize_phoenix/README.md Commands to download the example project and navigate into the directory. ```bash restate example python-openai-agents-examples cd python-openai-agents-examples/arize_phoenix ``` -------------------------------- ### Download the example Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/langfuse/README.md Downloads the example code for the Restate agent and Langfuse integration. ```bash restate example python-restate-agent-examples cd python-restate-agent-examples/langfuse ``` -------------------------------- ### Get the example Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/template/README.md Clones the TypeScript Restate agent example and installs its dependencies. ```bash restate example typescript-restate-agent && cd typescript-restate-agent npm install ``` -------------------------------- ### Download the example Source: https://github.com/restatedev/ai-examples/blob/main/pydantic-ai/examples/langfuse/README.md Downloads the Python Pydantic AI Langfuse example. ```bash restate example python-pydantic-ai-examples cd python-pydantic-ai-examples/langfuse ``` -------------------------------- ### Run example Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/README.md Command to run an example after changing directory into it. ```shell uv run . ``` -------------------------------- ### Start Tools Services Source: https://github.com/restatedev/ai-examples/blob/main/mcp/README.md Commands to navigate to the tools directory, install dependencies, and run the app. ```shell cd tools npm install npm run app ``` -------------------------------- ### Start Restate server and export Langfuse API keys Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/langfuse/README.md Start the Restate server and configure it to export traces to Langfuse by setting the tracing endpoint and headers. ```bash # Export Langfuse API keys source .env export RESTATE_TRACING_HEADERS__AUTHORIZATION="Basic $(echo -n "${LANGFUSE_PUBLIC_KEY}:${LANGFUSE_SECRET_KEY}" | base64)" restate-server --tracing-endpoint otlp+https://cloud.langfuse.com/api/public/otel/v1/traces ``` -------------------------------- ### Download the example Source: https://github.com/restatedev/ai-examples/blob/main/pydantic-ai/examples/logfire/README.md Downloads the Python Pydantic AI examples and navigates into the logfire directory. ```bash restate example python-pydantic-ai-examples cd python-pydantic-ai-examples/logfire ``` -------------------------------- ### Start Restate Server with Tracing Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/arize_phoenix/README.md Command to start the Restate server and configure it to export OpenTelemetry traces to Arize Phoenix. ```bash source .env export RESTATE_TRACING_HEADERS__AUTHORIZATION="Bearer ${PHOENIX_API_KEY}" restate-server --tracing-endpoint otlp+https://app.phoenix.arize.com/s/your-account-name/v1/traces ``` -------------------------------- ### Real-time Updates via PubSub Example Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-example-app/README.md Example of an agent publishing intermediate results to a pubsub topic. ```typescript onStepFinish: async (step) => { step.toolCalls.forEach((toolCall) => { pubsub.publish(topic, { role: "assistant", content: `Tool call: ${toolCall.toolName}(${JSON.stringify(toolCall.input)})` }, ctx.rand.uuidv4()); }); }, ``` -------------------------------- ### Add API keys to .env file Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/examples/langfuse/README.md Example of how to set up the .env file with necessary API keys for Langfuse and Google. ```bash echo 'LANGFUSE_PUBLIC_KEY=pk-lf-...' > .env echo 'LANGFUSE_SECRET_KEY=sk-lf-...' >> .env echo 'LANGFUSE_BASE_URL=https://cloud.langfuse.com' >> .env echo 'GOOGLE_API_KEY=AI...' >> .env ``` -------------------------------- ### Durable Tool Execution Example Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-example-app/README.md Example of wrapping tool calls into durable steps using ctx.run. ```typescript execute: async ({ expression }) => { return await ctx.run( `evaluating ${expression}`, async () => mathjs.evaluate(expression), { serde: superJson } ); }, ``` -------------------------------- ### Install Dependencies Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/interrupt-regenerate/README.md Installs project dependencies using npm. ```bash npm install ``` -------------------------------- ### Start Restate with Logfire tracing Source: https://github.com/restatedev/ai-examples/blob/main/pydantic-ai/examples/logfire/README.md Starts the Restate server and configures it to export OpenTelemetry traces to Logfire. ```bash # Export Logfire write token (=! API key) source .env export RESTATE_TRACING_HEADERS__AUTHORIZATION="Bearer $LOGFIRE_WRITE_TOKEN" restate-server --tracing-endpoint otlp+https://logfire-eu.pydantic.dev/v1/traces ``` -------------------------------- ### Install Restate Server & CLI Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/interrupt-regenerate/README.md Installs the Restate server and CLI using npm. ```bash npx @restatedev/restate-server ``` -------------------------------- ### Start Restate Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/tour-of-agents/README.md Start Restate using Docker. ```bash docker run --name restate_dev --rm \ -p 8080:8080 -p 9070:9070 -p 9071:9071 \ --add-host=host.docker.internal:host-gateway \ docker.restate.dev/restatedev/restate:latest ``` -------------------------------- ### Running a Specific Agent Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/tour-of-agents/README.md Example command to export the OpenAI API key and run the chat-agent.ts example. ```bash export OPENAI_API_KEY=sk-... npx tsx ./src/chat-agent.ts ``` -------------------------------- ### Start Restate Server Source: https://github.com/restatedev/ai-examples/blob/main/mcp/README.md Command to start the Restate Server. ```shell restate-server ``` -------------------------------- ### Durable LLM Calls Example Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-example-app/README.md Example of wrapping an LLM model for durable journaling of inference steps. ```typescript const model = wrapLanguageModel({ model: openai("gpt-5.4"), middleware: durableCalls(ctx, { maxRetryAttempts: 3 }), }); ``` -------------------------------- ### Get History (Interruption Path) Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/interrupt-regenerate/README.md Curl command to get the conversation history after an interruption. ```bash curl localhost:8080/CodingAgent/bob/get_history ``` -------------------------------- ### Get History (Happy Path) Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/interrupt-regenerate/README.md Curl command to get the conversation history after a successful task. ```bash curl localhost:8080/CodingAgent/alice/get_history ``` -------------------------------- ### Start the Agent Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/tour-of-agents/README.md Start the agent using tsx. ```shell npx tsx ./src/chat-agent.ts ``` -------------------------------- ### Invoking the agent via HTTP Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-example-app/README.md Example curl command to invoke the agent directly via HTTP. ```shell curl localhost:8080/agent/chat --json '{ "prompt": "A taxi driver earns $9461 per 1-hour of work. If he works 12 hours a day and in 1 hour he uses 12 liters of petrol with a price of $134 for 1 liter. How much money does he earn in one day?", "topic": "my-session" }' ``` -------------------------------- ### Start the Restate Server Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/tour-of-agents/README.md Start the Restate Server in a separate shell. ```shell npm install --global @restatedev/restate-server@latest @restatedev/restate@latest restate-server ``` -------------------------------- ### Install Restate Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/braintrust/README.md Install Restate server and client globally. ```bash npm install --global @restatedev/restate-server@latest @restatedev/restate@latest ``` -------------------------------- ### Start Restate Server Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/template/README.md Start the Restate Server in a separate shell. ```shell restate-server ``` -------------------------------- ### Google API Key Setup Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md This snippet shows how to set up the Google API Key by adding it to a .env file. ```shell echo "GOOGLE_API_KEY=your_api_key_here" >> .env ``` -------------------------------- ### Add API keys to .env file Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/langfuse/README.md Add your Langfuse and OpenAI API keys to a .env file. ```bash echo 'LANGFUSE_PUBLIC_KEY=pk-lf-...' > .env echo 'LANGFUSE_SECRET_KEY=sk-lf-...' >> .env echo 'LANGFUSE_BASE_URL=https://cloud.langfuse.com' >> .env echo 'OPENAI_API_KEY=sk-proj-...' >> .env ``` -------------------------------- ### Start Agent Service Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/interrupt-regenerate/README.md Starts the agent service with an OpenAI API key. ```bash OPENAI_API_KEY=sk-proj-... npm run dev ``` -------------------------------- ### Set OpenAI API Key Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/interrupt-regenerate/README.md Command to set the OpenAI API key in an .env file. ```bash echo 'OPENAI_API_KEY=sk-proj-...' > .env ``` -------------------------------- ### Durable Service Handler Example Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-example-app/README.md Example of an AI agent function running as a Restate durable service handler. ```typescript export default restate.service({ name: "agent", handlers: { chat: restate.handlers.handler( { /* schema */ }, async (ctx: restate.Context, { prompt, topic }) => { return await runAgent(ctx, prompt, topic); }, ), }, }); ``` -------------------------------- ### Restate-LangChain Integration Source: https://github.com/restatedev/ai-examples/blob/main/langchain-python/tour-of-agents/README.md Example of how to integrate RestateMiddleware with LangChain's create_agent. ```python from langchain.agents import create_agent from restate.ext.langchain import RestateMiddleware agent = create_agent(model=..., tools=[...], middleware=[RestateMiddleware()]) ``` -------------------------------- ### Register the service with Restate Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/langfuse/README.md Register the agent service with Restate so it knows where it is running. ```bash restate deployments add localhost:9080 ``` -------------------------------- ### Send a request to the agent Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/examples/langfuse/README.md Example cURL command to send a request to the insurance claim agent service running on Restate. ```bash curl localhost:8080/InsuranceClaimAgent/user123/run \ --json '{"text": "Customer ID: cus_123 - Hospital bill for broken leg treatment at General Hospital for 3000 euro on 24/04/26"}' ``` -------------------------------- ### Task Output Example Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md This is an example of the JSON output received when querying for task details. ```json { "id": 2, "jsonrpc": "2.0", "result": { "artifacts": [ { "artifactId": "d2ab957f-003d-49f7-b96d-1a5a83fee3b9", "description": null, "extensions": null, "metadata": null, "name": null, "parts": [ { "kind": "text", "metadata": null, "text": "Your reimbursement request with ID da52bd93-1927-4a62-8a15-eaafb29dd899 has been approved." } ] } ], "contextId": "5e00b4a6-dcc67-43ee-a389-0e2a65958444", "history": [ { "contextId": "5e00b4a6-dcc67-43ee-a389-0e2a65958444", "extensions": null, "kind": "message", "messageId": "9224947643702-7674c-417b-a0b0-f0741243c589", "metadata": null, "parts": [ { "kind": "text", "metadata": null, "text": "Reimburse my hotel for my business trip of 5 nights for 1200USD" } ], "referenceTaskIds": null, "role": "user", "taskId": "0d9g9ea6-dcc67-43ee-a389-8s9g0e6es5554" }, { "contextId": "5e00b4a6-dcc67-43ee-a389-0e2a65958444", "extensions": null, "kind": "message", "messageId": "92249e73702-767c-417b-a06b0-5sg6g881243c589", "metadata": null, "parts": [ { "kind": "text", "metadata": null, "text": "The date of the transaction is 05/04/2025" } ], "referenceTaskIds": null, "role": "user", "taskId": "0d9g9ea6-dcc67-43ee-a389-8s9g0e6es5554" }, { "contextId": null, "extensions": null, "kind": "message", "messageId": "89194646-702b-4af3-86d5-7c60355fbb77", "metadata": null, "parts": [ { "kind": "text", "metadata": null, "text": "MISSING_INFO: Please provide the date of the transaction." } ], "referenceTaskIds": null, "role": "agent", "taskId": null } ], "id": "9224947643702-7674c-417b-a0b0-f0741243c589", "kind": "task", "metadata": null, "status": { "message": null, "state": "completed", "timestamp": "2025-11-10T09:05:15.488894" } } } ``` -------------------------------- ### Send a request to the agent Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/langfuse/README.md Send a request to the agent service running on Restate. ```bash curl localhost:8080/InsuranceClaimAgent/run \ --json '{"text": "Customer ID: cus_123 - Hospital bill for broken leg treatment at General Hospital for 3000 euro on 24/04/26"}' ``` -------------------------------- ### Build MCP Server Source: https://github.com/restatedev/ai-examples/blob/main/mcp/README.md Commands to navigate to the restate-mcp directory, install dependencies, and build the server. ```shell cd restate-mcp npm install npm run build ``` -------------------------------- ### Environment Variables Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/examples/arize_phoenix/README.md Setting environment variables for API keys and collector endpoints. ```bash echo 'OPENAI_API_KEY=sk-proj-...' > .env echo 'PHOENIX_COLLECTOR_ENDPOINT=https://app.phoenix.arize.com/s/your-account-name' >> .env echo 'PHOENIX_API_KEY=...' >> .env echo 'PHOENIX_PROJECT_NAME=...' >> .env ``` -------------------------------- ### Add API keys to .env file Source: https://github.com/restatedev/ai-examples/blob/main/pydantic-ai/examples/logfire/README.md Creates or appends API keys for Logfire and OpenAI to the .env file. ```bash echo 'LOGFIRE_WRITE_TOKEN=your-write-token' >> .env echo 'OPENAI_API_KEY=sk-proj-...' >> .env ``` -------------------------------- ### Run the agent Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/template/README.md Exports the OpenAI API key and starts the development server for the agent. ```bash export OPENAI_API_KEY=sk-... npm run dev ``` -------------------------------- ### Register Services with Restate Server Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-template/README.md Registers the agent services with the Restate Server to enable durable execution. ```shell npx @restatedev/restate deployments register -y --use-http1.1 http://localhost:3000/restate/v1 ``` -------------------------------- ### Send Request to Agent Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-template/README.md Sends a request to the agent via the Restate Server endpoint. ```shell curl localhost:8080/agent/run --json '"What is the weather in Detroit?"' ``` -------------------------------- ### Export OpenAI API Key Source: https://github.com/restatedev/ai-examples/blob/main/openai-agents/tour-of-agents/README.md Export your OpenAI API key before running the examples. ```bash export OPENAI_API_KEY=your-key ``` -------------------------------- ### Send Message (Happy Path) Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/interrupt-regenerate/README.md Curl command to send a message to the agent for the happy path scenario. ```bash curl localhost:8080/CodingAgent/alice/message \ --json '{"content":"Write me a small todo CLI in Python."}' ``` -------------------------------- ### Interrupt with New Context Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/interrupt-regenerate/README.md Curl command to interrupt the ongoing task with new context. ```bash curl localhost:8080/CodingAgent/bob/message \ --json '{"content":"Actually, use FastAPI instead of Flask."}' ``` -------------------------------- ### Generate a greeting tool Source: https://github.com/restatedev/ai-examples/blob/main/mcp/README.md An example tool that generates a greeting for a person, including creating a greeting card image and an audio file. It utilizes Restate's `ctx.run` for executing tasks with retry capabilities and `all` for parallel execution. ```typescript tool( { description: "Greets a person with a song and dance", input: z.object({ name: z.string() }), }, async (ctx, { name }) => { const urls = await ctx.run( "Obtain two Pre-signed URLs for a bucket", () => generatePresignedUrls() ); const imageStep = ctx.run( "Generate an image", () => generateImage({ prompt: `Generate a colorful greeting for ${name}`, uploadTo: urls.imageUrl, }), { maxRetryAttempts: 3, } ); const audioStep = ctx.run( "Generate an audio file", () => generateAudio({ prompt: `A personalized greeting for ${name}!`, uploadTo: urls.audioUrl, }), { maxRetryAttempts: 3 } ); await all([imageStep, audioStep]); return { content: [ { type: "text", text: `Hello, ${name} there is a greeting card for you at ${urls.imageUrl} and a song ${urls.audioUrl}}!`, }, ], }; } ); ``` -------------------------------- ### Send First Message (Interruption Path) Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/interrupt-regenerate/README.md Curl command to send the first message in the interruption path (fire-and-forget). ```bash curl localhost:8080/CodingAgent/bob/message/send \ --json '{"content":"Build a Flask app with user auth."}' ``` -------------------------------- ### Register the AI SDK agents at Restate Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/nextjs-example-app/README.md Command to register the AI SDK agents with Restate using HTTP/1.1. ```shell npx @restatedev/restate deployments register http://localhost:3000/restate/v1 --use-http1.1 ``` -------------------------------- ### Get Task Details Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md This code snippet shows how to use curl to send a JSONRPC request to the ReimbursementAgentA2AServer to get task details. ```shell curl localhost:8080/ReimbursementAgentA2AServer/process_request --json '{ "jsonrpc": "2.0", "id": 2, "method":"tasks/get", "params": { "id": "0d9g9ea6-dcc67-43ee-a389-8s9g0e6es5554", "history_length": 10, "metadata": {} } }' | jq . ``` -------------------------------- ### Send a request to the agent Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/langfuse/README.md Sends a JSON request to the agent service running on Restate to process a reimbursement claim. ```bash curl localhost:8080/ClaimReimbursement/process \ --json '{"message": "Process my hospital bill of 2024-10-01 for 3000USD for a broken leg at General Hospital."}' ``` -------------------------------- ### Send requests to the agent Source: https://github.com/restatedev/ai-examples/blob/main/langchain-python/template/README.md Send a request to the agent to get the weather in San Francisco. ```shell curl localhost:8080/agent/run --json '{"message": "What is the weather in San Francisco?"}' ``` -------------------------------- ### Get Agent History Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/interrupt-regenerate/README.md Retrieves the conversation history for an agent. ```bash curl localhost:8080/CodingAgent/alice/getHistory ``` -------------------------------- ### Register Services with Restate Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/template/README.md Register the agent's services with the Restate Server to enable Restate Server to proxy invocations to the agent, adding durable execution. ```shell npx @restatedev/restate -y deployments register localhost:9080 ``` -------------------------------- ### Coding Task Python Code Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/interrupt-regenerate/README.md This snippet shows the Python code for the CodingTask, which performs LLM steps (plan, draft, polish) and handles cancellation signals. ```python import json from typing import Any from "restate.aio.service" import Service, ServiceContext from "restate.exceptions" import TerminalError class CodingTask(Service): async def run_task(self, ctx: ServiceContext, prompt: str) -> str: try: # Simulate LLM steps plan = await self.llm_plan(ctx, prompt) draft = await self.llm_draft(ctx, plan) polished_code = await self.llm_polish(ctx, draft) return polished_code except TerminalError: # Notify orchestrator and re-raise await ctx.send_event("task_cancelled", {}) raise async def llm_plan(self, ctx: ServiceContext, prompt: str) -> str: # Simulate LLM call for planning await ctx.sleep(1) print(f"LLM Plan: {prompt}") return f"plan for {prompt}" async def llm_draft(self, ctx: ServiceContext, plan: str) -> str: # Simulate LLM call for drafting await ctx.sleep(1) print(f"LLM Draft: {plan}") return f"draft based on {plan}" async def llm_polish(self, ctx: ServiceContext, draft: str) -> str: # Simulate LLM call for polishing await ctx.sleep(1) print(f"LLM Polish: {draft}") return f"polished code from {draft}" ``` -------------------------------- ### Send Request to Agent Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/template/README.md Send a request to the agent to get the weather information for a city. ```shell curl localhost:8080/agent/run --json '{ "message": "What is the weather like in San Francisco?", "user_id": "user-123" }' ``` -------------------------------- ### Agent Python Code Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/examples/interrupt-regenerate/README.md This snippet shows the Python code for the CodingAgent, which handles messages, manages conversation state, and interacts with the CodingTask. ```python from typing import List, Tuple from "restate.aio.virtual_object" import VirtualObject, HandledContext from "restate.aio.service" import Service, ServiceContext from "restate.aio.types" import Secret from "restate.exceptions" import TerminalError from coding_task import CodingTask class CodingAgent(VirtualObject): def __init__(self) -> None: self.conversation_history: List[Tuple[str, str]] = [] self.current_task_invocation_id: str | None = None async def message(self, ctx: HandledContext, content: str) -> None: if self.current_task_invocation_id: # Cancel the ongoing task if there is one await ctx.cancel_invocation(self.current_task_invocation_id) self.conversation_history.append(("user", "\n" + content)) else: self.conversation_history.append(("user", content)) task = CodingTask() invocation_id = await ctx.run_typed_invocation(task.run_task, content) self.current_task_invocation_id = invocation_id # We don't await the task here, it runs in the background # The invocation ID is stored so we can cancel it later async def get_history(self, ctx: HandledContext) -> List[Tuple[str, str]]: return self.conversation_history class CodingAgentService(Service): async def message(self, ctx: ServiceContext, agent_id: str, content: str) -> None: agent = await ctx.get_virtual_object(CodingAgent, agent_id) await agent.message(ctx.handled(), content) async def message_send(self, ctx: ServiceContext, agent_id: str, content: str) -> None: # Fire-and-forget for the first message agent = await ctx.get_virtual_object(CodingAgent, agent_id) ctx.background_invocation(agent.message(ctx.handled(), content)) async def get_history(self, ctx: ServiceContext, agent_id: str) -> List[Tuple[str, str]]: agent = await ctx.get_virtual_object(CodingAgent, agent_id) return await agent.get_history(ctx.handled()) ``` -------------------------------- ### Start a new reimbursement task Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md This curl command initiates a new reimbursement task by sending a message to the ReimbursementAgentA2AServer. ```shell curl localhost:8080/ReimbursementAgentA2AServer/process_request \ --json '{ \ "jsonrpc": "2.0", \ "id": 1424443, \ "method": "message/send", \ "params": { \ "message": { \ "role": "user", \ "parts": [ \ { \ "kind": "text", \ "text": "Reimburse my hotel for my business trip of 5 nights for 1200USD of 05/04/2025" \ } \ ], \ "messageId": "92249e73702-7674c-417b-a0b0-f0741243c449", \ "taskId": "33349e733702-7674c-417b-a0b0-f0741243c333" \ }, \ "metadata": {} \ } \ }' | jq . ``` -------------------------------- ### Send a Request to the Agent Source: https://github.com/restatedev/ai-examples/blob/main/vercel-ai/template/README.md Send a request to the agent. The request targets Restate Server's endpoint (8080) because the server proxies requests to the service, making them durable. ```shell curl localhost:8080/agent/run --json '{"prompt": "What is the weather in San Francisco?"}' ``` -------------------------------- ### Start a task that blocks on human approval Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md This command initiates a reimbursement request and requires human approval, demonstrating the initial step in a multi-turn conversation. ```shell curl localhost:8080/ReimbursementAgentA2AServer/process_request \ --json '{ \ "jsonrpc": "2.0", \ "id": 1424643, \ "method": "message/send", \ "params": { \ "message": { \ "role": "user", \ "parts": [ \ { \ "kind": "text", \ "text": "Reimburse my hotel for my business trip of 5 nights for 1200USD" \ } \ ], \ "taskId": "0d9g9ea6-dcc67-43ee-a389-8s9g0e6es5554", \ "contextId": "5e00b4a6-dcc67-43ee-a389-0e2a65958444", \ "messageId": "9224947643702-7674c-417b-a0b0-f0741243c589" \ }, \ "metadata": {} \ } \ }' | jq . ``` -------------------------------- ### Get Interrupted Agent History Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/interrupt-regenerate/README.md Retrieves the conversation history after an interruption. ```bash curl localhost:8080/CodingAgent/bob/getHistory ``` -------------------------------- ### Register the Services Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/tour-of-agents/README.md Register the services with Restate. Use --force if you already had another deployment registered at 9080. ```shell restate -y deployments register localhost:9080 --force ``` -------------------------------- ### Run an agent Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/tour-of-agents/README.md Run a specific agent. ```bash uv run app/chat_agent.py ``` -------------------------------- ### Register the deployment Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/tour-of-agents/README.md Register the Restate deployment. ```bash curl localhost:9070/deployments --json '{"uri": "http://host.docker.internal:9080"}' ``` -------------------------------- ### Run Restate Server Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/braintrust/README.md Run Restate server with the configuration file. ```shell restate-server --config-file restate.toml ``` -------------------------------- ### Register Services Source: https://github.com/restatedev/ai-examples/blob/main/mcp/README.md Command to register the services with the Restate server. Use `--force` if a deployment already exists. ```shell restate -y deployments register localhost:9080 ``` -------------------------------- ### Cancel the reimbursement task Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md This curl command cancels the previously started reimbursement task using its task ID. ```shell curl localhost:8080/ReimbursementAgentA2AServer/process_request \ --json '{ \ "jsonrpc": "2.0", \ "id": 3, \ "method":"tasks/cancel", \ "params": { \ "id": "33349e733702-7674c-417b-a0b0-f0741243c333" \ } \ }' | jq . ``` -------------------------------- ### Export Google API Key Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/template/README.md Export your Google API key as an environment variable. Obtain an API key from Google AI Studio. ```shell export GOOGLE_API_KEY=your_google_api_key_here ``` -------------------------------- ### Claude Desktop Configuration Source: https://github.com/restatedev/ai-examples/blob/main/mcp/README.md JSON configuration for Claude desktop to specify the MCP server command and arguments. ```json { "mcpServers": { "restate": { "command": "node", "args": [ "/path/to/mcp-example/restate-mcp/build" ] } } } ``` -------------------------------- ### Export OpenAI API key Source: https://github.com/restatedev/ai-examples/blob/main/langchain-python/template/README.md Export your OpenAI or Anthropic API key as an environment variable. ```shell export OPENAI_API_KEY=your_openai_api_key ``` -------------------------------- ### Export API Key Source: https://github.com/restatedev/ai-examples/blob/main/mcp/README.md Command to export the OpenAI or Anthropic API key as an environment variable. ```shell export OPENAI_API_KEY=your_openai_api_key ``` -------------------------------- ### Export API Keys and Run Agent Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/braintrust/README.md Export necessary API keys and run the agent. ```bash export BRAINTRUST_API_KEY=sk-... export BRAINTRUST_PROJECT_ID=... export OPENAI_API_KEY=sk-... npm run dev ``` -------------------------------- ### Register Services Source: https://github.com/restatedev/ai-examples/blob/main/google-adk/template/README.md Register the services with the Restate CLI. ```shell restate -y deployments register localhost:9080 ``` -------------------------------- ### Run Reimbursement Agent Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md Command to run the reimbursement agent application using UV. ```shell uv run app/reimbursement ``` -------------------------------- ### Run Weather Agent Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md Command to run the weather agent application using UV. ```shell uv run app/weather ``` -------------------------------- ### Send Message to Agent Source: https://github.com/restatedev/ai-examples/blob/main/python-restate-only/template/README.md Send a message to the agent. ```shell curl localhost:8080/agent/run --json '{"message":"What is the weather in San Francisco?"}' ``` -------------------------------- ### Competitive Racing Agents Source: https://github.com/restatedev/ai-examples/blob/main/README.md Run parallel agents and use the fastest response, canceling others. ```python python-restate-only/tour-of-agents/app/racing_agents.py ``` ```typescript typescript-restate-only/tour-of-agents/src/racing-agents.ts ``` -------------------------------- ### Restate Configuration Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/braintrust/README.md Restate configuration file with Braintrust tracing endpoint and headers. ```toml tracing-endpoint="otlp+https://api.braintrust.dev/otel/v1/traces" [tracing-headers] authorization="Bearer your-braintrust-api-key" x-bt-parent="project_id:your-project-id" ``` -------------------------------- ### Send First Message for Interruption Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/interrupt-regenerate/README.md Sends the initial message to the agent, fire-and-forget. ```bash curl localhost:8080/CodingAgent/bob/message/send \ --json '{"content":"Build a Fastify app with user auth."}' ``` -------------------------------- ### Provide the date of the transaction Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md This command continues the conversation by providing the missing transaction date, demonstrating how to respond to agent requests for more information. ```shell curl localhost:8080/ReimbursementAgentA2AServer/process_request \ --json '{ \ "jsonrpc": "2.0", \ "id": 1423, \ "method": "message/send", \ "params": { \ "message": { \ "role": "user", \ "parts": [ \ { \ "kind": "text", \ "text": "The date of the transaction is 05/04/2025" \ } \ ], \ "taskId": "0d9g9ea6-dcc67-43ee-a389-8s9g0e6es5554", \ "contextId": "5e00b4a6-dcc67-43ee-a389-0e2a65958444", \ "messageId": "92249e73702-7674c-417b-a06b0-5sg6g881243c589" \ }, \ "metadata": {} \ } \ }' | jq . ``` -------------------------------- ### Register the agent Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/template/README.md Registers the local agent with the Restate server. ```bash restate deployments register http://localhost:9080 --force --yes ``` -------------------------------- ### Agent output for initial request Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md This JSON output shows the agent's response to the initial reimbursement request, indicating that it requires more information (the transaction date). ```json { "id": 1424643, "jsonrpc": "2.0", "result": { "artifacts": null, "contextId": "5e00b4a6-dcc67-43ee-a389-0e2a65958444", "history": [ { "contextId": "5e00b4a6-dcc67-43ee-a389-0e2a65958444", "extensions": null, "kind": "message", "messageId": "9224947643702-7674c-417b-a0b0-f0741243c589", "metadata": null, "parts": [ { "kind": "text", "metadata": null, "text": "Reimburse my hotel for my business trip of 5 nights for 1200USD" } ], "referenceTaskIds": null, "role": "user", "taskId": "0d9g9ea6-dcc67-43ee-a389-8s9g0e6es5554" } ], "id": "9224947643702-7674c-417b-a0b0-f0741243c589", "kind": "task", "metadata": null, "status": { "message": { "contextId": null, "extensions": null, "kind": "message", "messageId": "89194646-702b-4af3-86d5-7c60355fbb77", "metadata": null, "parts": [ { "kind": "text", "metadata": null, "text": "MISSING_INFO: Please provide the date of the transaction." } ], "referenceTaskIds": null, "role": "agent", "taskId": null }, "state": "input-required", "timestamp": "2025-11-10T08:57:25.462064" } } } ``` -------------------------------- ### Happy Path Message Source: https://github.com/restatedev/ai-examples/blob/main/typescript-restate-only/examples/interrupt-regenerate/README.md Sends a message to the agent for a full plan/draft/polish cycle. ```bash curl localhost:8080/CodingAgent/alice/message \ --json '{"content":"Write me a small todo CLI in TypeScript."}' ``` -------------------------------- ### Interrupt & Regenerate Source: https://github.com/restatedev/ai-examples/blob/main/README.md Interrupt a running agent with new context; cancel in-flight task and restart. ```python python-restate-only/examples/interrupt-regenerate/agent.py ``` ```typescript typescript-restate-only/examples/interrupt-regenerate/src/agent.ts ``` -------------------------------- ### Agent logs indicating reimbursement approval Source: https://github.com/restatedev/ai-examples/blob/main/a2a/README.md These log snippets show the agent's internal process, including calling an LLM and executing the 'reimburse' tool, culminating in a curl command to approve the request. ```text ... first part of logs ... [2025-05-16 13:42:50,410] [310993] [INFO] - Agent session lwp13w5e3sdf258t3wesf13234 - Starting iteration of agent loop with agent: ReimbursementAgent and tools/handoffs: ['create_request_form', 'reimburse', 'return_form'] [2025-05-16 13:42:50,410] [310993] [INFO] - Agent session lwp13w5e3sdf258t3wesf13234 - Calling LLM [2025-05-16 13:42:52,293] [310993] [INFO] - HTTP Request: POST https://api.openai.com/v1/responses "HTTP/1.1 200 OK" [2025-05-16 13:42:52,303] [310993] [INFO] - Agent session lwp13w5e3sdf258t3wesf13234 - Executing tool reimburse ================================================== Requesting approval for request_id_1633297 Resolve via: curl localhost:8080/restate/awakeables/sign_1oqmHpDF_RJQBltjnf48zszmfmRr4w9izAAAAEQ/resolve --json '{"approved": true}' ```