From 2062d62d56f9bf2fa82109487d5c8793cea8a6b1 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sun, 23 Feb 2025 10:49:28 -0500 Subject: [PATCH 01/41] wip --- public/_redirects | 3 + .../agents/api-reference/configuration.mdx | 28 +++++ .../docs/agents/api-reference/index.mdx | 13 ++ src/content/docs/agents/api-reference/sdk.mdx | 31 +++++ .../docs/agents/building-with-ai/index.mdx | 13 ++ .../{build => building-with-ai}/llms.txt.mdx | 2 +- .../prompting.mdx} | 2 +- .../capabilities/control-web-browsers.mdx | 10 -- .../docs/agents/capabilities/mcp-server.mdx | 114 ------------------ .../docs/agents/capabilities/run-models.mdx | 9 -- .../docs/agents/capabilities/send-email.mdx | 11 -- .../agents/capabilities/webrtc-realtime.mdx | 9 -- .../docs/agents/concepts/calling-llms.mdx | 11 ++ .../concepts/communcating-with-users.mdx | 11 ++ .../docs/agents/{build => concepts}/index.mdx | 6 +- .../docs/agents/concepts/what-are-agents.mdx | 14 +++ .../docs/agents/concepts/workflows.mdx | 14 +++ .../docs/agents/examples/ask-ai-models.mdx | 11 ++ .../docs/agents/examples/browse-the-web.mdx | 10 ++ src/content/docs/agents/examples/evals.mdx | 11 ++ .../{capabilities => examples}/index.mdx | 6 +- .../docs/agents/examples/persist-data.mdx | 11 ++ src/content/docs/agents/examples/rag.mdx | 11 ++ .../docs/agents/examples/run-workflows.mdx | 12 ++ .../docs/agents/examples/schedule-tasks.mdx | 11 ++ .../docs/agents/examples/self-host.mdx | 11 ++ .../docs/agents/examples/send-emails.mdx | 11 ++ .../agents/examples/testing-your-agents.mdx | 11 ++ .../docs/agents/examples/websockets.mdx | 11 ++ .../docs/agents/getting-started/index.mdx | 13 ++ .../getting-started/observing-agents.mdx | 19 +++ .../agents/getting-started/quick-start.mdx | 44 +++++++ .../getting-started/testing-your-agent.mdx | 11 ++ .../writing-your-first-agent.mdx | 19 +++ src/content/docs/agents/index.mdx | 34 +++++- .../docs/agents/products/ai-gateway.mdx | 11 -- .../docs/agents/products/durable-objects.mdx | 11 -- .../docs/agents/products/email-workers.mdx | 11 -- .../docs/agents/products/real-time.mdx | 11 -- .../docs/agents/products/workers-ai.mdx | 11 -- .../docs/agents/products/workflows.mdx | 11 -- .../agents/reference-architectures/index.mdx | 14 --- .../agents/reference-architectures/rag.mdx | 9 -- .../reference-architectures/text-and-call.mdx | 9 -- .../agents/reference/agents-vs-workflows.mdx | 15 +++ .../agents/{products => reference}/index.mdx | 6 +- 46 files changed, 418 insertions(+), 269 deletions(-) create mode 100644 src/content/docs/agents/api-reference/configuration.mdx create mode 100644 src/content/docs/agents/api-reference/index.mdx create mode 100644 src/content/docs/agents/api-reference/sdk.mdx create mode 100644 src/content/docs/agents/building-with-ai/index.mdx rename src/content/docs/agents/{build => building-with-ai}/llms.txt.mdx (93%) rename src/content/docs/agents/{build/prompts.mdx => building-with-ai/prompting.mdx} (99%) delete mode 100644 src/content/docs/agents/capabilities/control-web-browsers.mdx delete mode 100644 src/content/docs/agents/capabilities/mcp-server.mdx delete mode 100644 src/content/docs/agents/capabilities/run-models.mdx delete mode 100644 src/content/docs/agents/capabilities/send-email.mdx delete mode 100644 src/content/docs/agents/capabilities/webrtc-realtime.mdx create mode 100644 src/content/docs/agents/concepts/calling-llms.mdx create mode 100644 src/content/docs/agents/concepts/communcating-with-users.mdx rename src/content/docs/agents/{build => concepts}/index.mdx (82%) create mode 100644 src/content/docs/agents/concepts/what-are-agents.mdx create mode 100644 src/content/docs/agents/concepts/workflows.mdx create mode 100644 src/content/docs/agents/examples/ask-ai-models.mdx create mode 100644 src/content/docs/agents/examples/browse-the-web.mdx create mode 100644 src/content/docs/agents/examples/evals.mdx rename src/content/docs/agents/{capabilities => examples}/index.mdx (73%) create mode 100644 src/content/docs/agents/examples/persist-data.mdx create mode 100644 src/content/docs/agents/examples/rag.mdx create mode 100644 src/content/docs/agents/examples/run-workflows.mdx create mode 100644 src/content/docs/agents/examples/schedule-tasks.mdx create mode 100644 src/content/docs/agents/examples/self-host.mdx create mode 100644 src/content/docs/agents/examples/send-emails.mdx create mode 100644 src/content/docs/agents/examples/testing-your-agents.mdx create mode 100644 src/content/docs/agents/examples/websockets.mdx create mode 100644 src/content/docs/agents/getting-started/index.mdx create mode 100644 src/content/docs/agents/getting-started/observing-agents.mdx create mode 100644 src/content/docs/agents/getting-started/quick-start.mdx create mode 100644 src/content/docs/agents/getting-started/testing-your-agent.mdx create mode 100644 src/content/docs/agents/getting-started/writing-your-first-agent.mdx delete mode 100644 src/content/docs/agents/products/ai-gateway.mdx delete mode 100644 src/content/docs/agents/products/durable-objects.mdx delete mode 100644 src/content/docs/agents/products/email-workers.mdx delete mode 100644 src/content/docs/agents/products/real-time.mdx delete mode 100644 src/content/docs/agents/products/workers-ai.mdx delete mode 100644 src/content/docs/agents/products/workflows.mdx delete mode 100644 src/content/docs/agents/reference-architectures/index.mdx delete mode 100644 src/content/docs/agents/reference-architectures/rag.mdx delete mode 100644 src/content/docs/agents/reference-architectures/text-and-call.mdx create mode 100644 src/content/docs/agents/reference/agents-vs-workflows.mdx rename src/content/docs/agents/{products => reference}/index.mdx (71%) diff --git a/public/_redirects b/public/_redirects index f7d12fde3948e1d..097930fe8efaab5 100644 --- a/public/_redirects +++ b/public/_redirects @@ -96,6 +96,9 @@ /access/ssh/short-live-cert-server/ /cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/ 301 /access/ssh/ssh-guide/ /cloudflare-one/connections/connect-networks/use-cases/ssh/ 301 +# agents +/agents/build/prompts/ /agents/building-with-ai/prompting/ 301 + # ai /ai/ /use-cases/ai/ 301 diff --git a/src/content/docs/agents/api-reference/configuration.mdx b/src/content/docs/agents/api-reference/configuration.mdx new file mode 100644 index 000000000000000..115d4a401cd62a5 --- /dev/null +++ b/src/content/docs/agents/api-reference/configuration.mdx @@ -0,0 +1,28 @@ +--- +title: Agents SDK +pcx_content_type: concept +sidebar: + order: 2 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +This guide details the Agents API within Cloudflare Workers, including methods, types, and usage examples. + +## Agent + +TODO + +The `Agent` class is the core element of a Agent definition: + +```ts +import { Agent } from "@cloudflare/agents"; + +export class MyAgent extends Agent { + // methods here + async onRequest(req: Request) { + + } +}; +``` \ No newline at end of file diff --git a/src/content/docs/agents/api-reference/index.mdx b/src/content/docs/agents/api-reference/index.mdx new file mode 100644 index 000000000000000..a11a64bb8f59f7b --- /dev/null +++ b/src/content/docs/agents/api-reference/index.mdx @@ -0,0 +1,13 @@ +--- +title: Agents API Reference +pcx_content_type: navigation +sidebar: + order: 3 + group: + hideIndex: true + +--- + +import { DirectoryListing } from "~/components" + + diff --git a/src/content/docs/agents/api-reference/sdk.mdx b/src/content/docs/agents/api-reference/sdk.mdx new file mode 100644 index 000000000000000..6d63f89936c781a --- /dev/null +++ b/src/content/docs/agents/api-reference/sdk.mdx @@ -0,0 +1,31 @@ +--- +title: Configuration +pcx_content_type: concept +sidebar: + order: 3 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO - how to configure an Agent + + + +```json +{ + "name": "my-agent", + "script": "src/index.ts", + // @cloudflare/agents uses Durable Objects + "durable_objects": { + "bindings": [ + { + "binding": "MyAgent", + "class_name": "MyAgent" + } + ] + } +} +``` + + \ No newline at end of file diff --git a/src/content/docs/agents/building-with-ai/index.mdx b/src/content/docs/agents/building-with-ai/index.mdx new file mode 100644 index 000000000000000..cfb5f75f9dd48bf --- /dev/null +++ b/src/content/docs/agents/building-with-ai/index.mdx @@ -0,0 +1,13 @@ +--- +title: Building with AI +pcx_content_type: navigation +sidebar: + order: 5 + group: + hideIndex: true + +--- + +import { DirectoryListing } from "~/components" + + diff --git a/src/content/docs/agents/build/llms.txt.mdx b/src/content/docs/agents/building-with-ai/llms.txt.mdx similarity index 93% rename from src/content/docs/agents/build/llms.txt.mdx rename to src/content/docs/agents/building-with-ai/llms.txt.mdx index 2f46b6a2c61acb7..afee3b4774aed84 100644 --- a/src/content/docs/agents/build/llms.txt.mdx +++ b/src/content/docs/agents/building-with-ai/llms.txt.mdx @@ -3,7 +3,7 @@ pcx_content_type: navigation title: llms.txt external_link: /llms.txt sidebar: - order: 20 + order: 102 head: [] description: Provide context to your AI models & tools when building on Cloudflare. --- diff --git a/src/content/docs/agents/build/prompts.mdx b/src/content/docs/agents/building-with-ai/prompting.mdx similarity index 99% rename from src/content/docs/agents/build/prompts.mdx rename to src/content/docs/agents/building-with-ai/prompting.mdx index ab7c97f65532b8c..a5416bbf223a213 100644 --- a/src/content/docs/agents/build/prompts.mdx +++ b/src/content/docs/agents/building-with-ai/prompting.mdx @@ -2,7 +2,7 @@ title: Prompting AI Models pcx_content_type: concept sidebar: - order: 2 + order: 101 --- import { Tabs, TabItem, GlossaryTooltip, Type, Badge, TypeScriptExample } from "~/components"; diff --git a/src/content/docs/agents/capabilities/control-web-browsers.mdx b/src/content/docs/agents/capabilities/control-web-browsers.mdx deleted file mode 100644 index 5193b4b42722c48..000000000000000 --- a/src/content/docs/agents/capabilities/control-web-browsers.mdx +++ /dev/null @@ -1,10 +0,0 @@ ---- -pcx_content_type: navigation -title: Control Web Browsers (Browser Rendering API) -external_link: /browser-rendering/ -sidebar: - order: 2 -head: [] -description: The Workers Browser Rendering API allows developers to programmatically control and interact with a headless browser instance and create automation flows for their applications and products. - ---- diff --git a/src/content/docs/agents/capabilities/mcp-server.mdx b/src/content/docs/agents/capabilities/mcp-server.mdx deleted file mode 100644 index 7e5a1479d567e76..000000000000000 --- a/src/content/docs/agents/capabilities/mcp-server.mdx +++ /dev/null @@ -1,114 +0,0 @@ ---- -pcx_content_type: tutorial -title: Build an MCP Server -sidebar: - order: 1 - group: - hideIndex: true -description: Build and deploy an MCP server on Cloudflare Workers ---- -[Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) is an open standard that allows AI assistants & LLMs to interact with services directly. If you want users to access your service or product straight from their AI assistant, you can enable this by spinning up an MCP server for your application. - -## Building an MCP Server on Cloudflare Workers - -Normally, setting up an MCP server requires writing boilerplate code to handle routing, define types, and standing up a server that implements the MCP protocol. But with [Cloudflare Workers](/workers/), all the heavy lifting is done for you, so all you need to do is define your service's functionality as TypeScript methods on your Worker -Once deployed, your Worker becomes an MCP server that AI assistants (as long as they support MCP) can connect to and use to interact with your service. - -## Benefits - -- **Minimal setup & built-in boilerplate:** The Worker automatically handles API routing, server management, and MCP protocol compliance. The [workers-mcp](https://www.npmjs.com/package/workers-mcp) package bootstraps your MCP server, allowing you to focus on your service logic. -- **Automatic documentation:** Public methods annotated with JSDoc are automatically documented and exposed as MCP tools. This means AI assistants can quickly understand how to interact with your service, making tool discovery and integration much easier. -- **Scalability & performance:** Deploy your MCP server on Cloudflare's global edge network so that users can make fast, performant requests from their LLMs. Cloudflare will handle traffic spikes and high load, ensuring your service remains available and responsive. -- **Expand MCP server capabilities:** Easily connect to Workers AI, D1, Durable Objects, and other Cloudflare services to add more functionality to your MCP Server. - -## Get Started - -Follow these steps to create and deploy your own MCP server on Cloudflare Workers. - - -### 1. Create a new Worker - -If you haven't already, install [Wrangler](https://developers.cloudflare.com/workers/wrangler/) and log in: - -```bash -npm install wrangler -wrangler login -``` - -Initialize a new project: -```bash -npx create-cloudflare@latest my-mcp-worker -cd my-mcp-worker -``` - -### 2. Install the MCP Tooling -Inside your project directory, install the [workers-mcp](https://github.com/cloudflare/workers-mcp) package: - -```bash -npm install workers-mcp -``` - -This package provides the tools needed to run your Worker as an MCP server. - -### 3. Configure your Worker to support MCP -Run the following setup command: - -```bash -npx workers-mcp setup -``` - -This guided installation process takes a brand new or existing Workers project and adds the required tooling to turn it into an MCP server: -- Automatic documentation generation -- Shared-secret security using Wrangler Secrets -- Installs a local proxy so you can access it from your MCP desktop clients (like Claude Desktop) - -### 4. Set up the MCP Server -Replace the contents of your src/index.ts with the following boilerplate code: - -```ts -import { WorkerEntrypoint } from 'cloudflare:workers'; -import { ProxyToSelf } from 'workers-mcp'; - -export default class MyWorker extends WorkerEntrypoint { - /** - * A warm, friendly greeting from your new MCP server. - * @param name {string} The name of the person to greet. - * @return {string} The greeting message. - */ - sayHello(name: string) { - return `Hello from an MCP Worker, ${name}!`; - } - - /** - * @ignore - */ - async fetch(request: Request): Promise { - // ProxyToSelf handles MCP protocol compliance. - return new ProxyToSelf(this).fetch(request); - } -} -``` - -This converts your Cloudflare Worker into an MCP server, enabling interactions with AI assistants. The key components are: -- **WorkerEntrypoint:** The WorkerEntrypoint class handles all incoming request management and routing. This provides the structure needed to expose MCP tools within the Worker. -- **Tool Definition:** Methods, for example, sayHello, are annotated with JSDoc, which automatically registers the method as an MCP tool. AI assistants can call this method dynamically, passing a name and receiving a greeting in response. Additional tools can be defined using the same pattern. -- **ProxyToSelf:** MCP servers must follow a specific request/response format. ProxyToSelf ensures that incoming requests are properly routed to the correct MCP tools. Without this, you would need to manually parse requests and validate responses. - - -**Note:** Every public method that is annotated with JSDoc becomes an MCP tool that is discoverable by AI assistants. - - -### 5. Deploy the MCP Server -Update your [Wrangler configuration file](/workers/wrangler/configuration/) with the appropriate configuration then deploy your Worker: -```bash -wrangler deploy -``` - -Your MCP server is now deployed globally and all your public class methods are exposed as MCP tools that AI assistants can now interact with. - -### Expanding the MCP Server Capabilities -Use existing Cloudflare products to expand the functionality of your MCP server. You can: -- Send emails using [Email Routing](/email-routing/) -- Capture and share website previews using [Browser Rendering](/browser-rendering/) -- Store and manage sessions, user data, or other persistent information with [Durable Objects](/durable-objects/) -- Query and update data using a [D1 database](/d1/) diff --git a/src/content/docs/agents/capabilities/run-models.mdx b/src/content/docs/agents/capabilities/run-models.mdx deleted file mode 100644 index d60f7d78e66c731..000000000000000 --- a/src/content/docs/agents/capabilities/run-models.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -pcx_content_type: navigation -title: Run models (Workers AI) -external_link: /workers-ai/ -sidebar: - order: 3 -head: [] -description: Run popular open-source AI models on Cloudflare's network. ---- \ No newline at end of file diff --git a/src/content/docs/agents/capabilities/send-email.mdx b/src/content/docs/agents/capabilities/send-email.mdx deleted file mode 100644 index ed1d9a9240f7365..000000000000000 --- a/src/content/docs/agents/capabilities/send-email.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -pcx_content_type: navigation -title: Send Email -external_link: /email-routing/email-workers/send-email-workers/ -sidebar: - order: 4 -head: [] -description: Send emails from your Worker for async updates to a user. ---- - - diff --git a/src/content/docs/agents/capabilities/webrtc-realtime.mdx b/src/content/docs/agents/capabilities/webrtc-realtime.mdx deleted file mode 100644 index 0da8a27eff545a4..000000000000000 --- a/src/content/docs/agents/capabilities/webrtc-realtime.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -pcx_content_type: navigation -title: Realtime voice (WebRTC) -external_link: /calls/ -sidebar: - order: 5 -head: [] -description: Build real-time serverless video, audio and data applications. ---- \ No newline at end of file diff --git a/src/content/docs/agents/concepts/calling-llms.mdx b/src/content/docs/agents/concepts/calling-llms.mdx new file mode 100644 index 000000000000000..84cf31bc4217f53 --- /dev/null +++ b/src/content/docs/agents/concepts/calling-llms.mdx @@ -0,0 +1,11 @@ +--- +title: Communicating with users +pcx_content_type: concept +sidebar: + order: 4 + +--- + +import { Render } from "~/components"; + +calling LLMs \ No newline at end of file diff --git a/src/content/docs/agents/concepts/communcating-with-users.mdx b/src/content/docs/agents/concepts/communcating-with-users.mdx new file mode 100644 index 000000000000000..00f048f7f045c06 --- /dev/null +++ b/src/content/docs/agents/concepts/communcating-with-users.mdx @@ -0,0 +1,11 @@ +--- +title: Calling LLMs +pcx_content_type: concept +sidebar: + order: 3 + +--- + +import { Render } from "~/components"; + +calling LLMs \ No newline at end of file diff --git a/src/content/docs/agents/build/index.mdx b/src/content/docs/agents/concepts/index.mdx similarity index 82% rename from src/content/docs/agents/build/index.mdx rename to src/content/docs/agents/concepts/index.mdx index b75d6ff811c8788..f0c26ca975dc153 100644 --- a/src/content/docs/agents/build/index.mdx +++ b/src/content/docs/agents/concepts/index.mdx @@ -1,14 +1,12 @@ --- pcx_content_type: reference -title: Build +title: Concepts sidebar: - order: 10 + order: 1 group: hideIndex: true --- import { DirectoryListing } from "~/components"; -Build - diff --git a/src/content/docs/agents/concepts/what-are-agents.mdx b/src/content/docs/agents/concepts/what-are-agents.mdx new file mode 100644 index 000000000000000..f4491215cbe2877 --- /dev/null +++ b/src/content/docs/agents/concepts/what-are-agents.mdx @@ -0,0 +1,14 @@ +--- +title: Workflows +pcx_content_type: concept +sidebar: + order: 1 + +--- + +import { Render } from "~/components"; + +TODO - what are agents? + +- terminology +- diagram: orchestrator / container / task / workflow diff --git a/src/content/docs/agents/concepts/workflows.mdx b/src/content/docs/agents/concepts/workflows.mdx new file mode 100644 index 000000000000000..37cebb9623ed7c9 --- /dev/null +++ b/src/content/docs/agents/concepts/workflows.mdx @@ -0,0 +1,14 @@ +--- +title: What are Agents +pcx_content_type: concept +sidebar: + order: 2 + +--- + +import { Render } from "~/components"; + +TODO - what are agents? + +- terminology +- diagram: orchestrator / container / task / workflow diff --git a/src/content/docs/agents/examples/ask-ai-models.mdx b/src/content/docs/agents/examples/ask-ai-models.mdx new file mode 100644 index 000000000000000..60ce09fee41e29c --- /dev/null +++ b/src/content/docs/agents/examples/ask-ai-models.mdx @@ -0,0 +1,11 @@ +--- +title: Asynchronous Workflows +pcx_content_type: concept +sidebar: + order: 7 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/examples/browse-the-web.mdx new file mode 100644 index 000000000000000..0739d352fa96527 --- /dev/null +++ b/src/content/docs/agents/examples/browse-the-web.mdx @@ -0,0 +1,10 @@ +--- +title: Self-hosting Agents +pcx_content_type: concept +sidebar: + order: 99 +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO - send emails diff --git a/src/content/docs/agents/examples/evals.mdx b/src/content/docs/agents/examples/evals.mdx new file mode 100644 index 000000000000000..a4be57bc6a0b112 --- /dev/null +++ b/src/content/docs/agents/examples/evals.mdx @@ -0,0 +1,11 @@ +--- +title: Asynchronous Workflows +pcx_content_type: concept +sidebar: + order: 15 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO diff --git a/src/content/docs/agents/capabilities/index.mdx b/src/content/docs/agents/examples/index.mdx similarity index 73% rename from src/content/docs/agents/capabilities/index.mdx rename to src/content/docs/agents/examples/index.mdx index dfcca68ba21de99..97954a89801c9f6 100644 --- a/src/content/docs/agents/capabilities/index.mdx +++ b/src/content/docs/agents/examples/index.mdx @@ -1,14 +1,14 @@ --- pcx_content_type: reference -title: Capabilities +title: Build sidebar: - order: 2 + order: 4 group: hideIndex: true --- import { DirectoryListing } from "~/components"; -Capabilities +Build AI Agents on Cloudflare diff --git a/src/content/docs/agents/examples/persist-data.mdx b/src/content/docs/agents/examples/persist-data.mdx new file mode 100644 index 000000000000000..f87a18d642f6871 --- /dev/null +++ b/src/content/docs/agents/examples/persist-data.mdx @@ -0,0 +1,11 @@ +--- +title: Retrieval Augmented Generation +pcx_content_type: concept +sidebar: + order: 6 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO diff --git a/src/content/docs/agents/examples/rag.mdx b/src/content/docs/agents/examples/rag.mdx new file mode 100644 index 000000000000000..60ce09fee41e29c --- /dev/null +++ b/src/content/docs/agents/examples/rag.mdx @@ -0,0 +1,11 @@ +--- +title: Asynchronous Workflows +pcx_content_type: concept +sidebar: + order: 7 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO diff --git a/src/content/docs/agents/examples/run-workflows.mdx b/src/content/docs/agents/examples/run-workflows.mdx new file mode 100644 index 000000000000000..316d622e4d4f448 --- /dev/null +++ b/src/content/docs/agents/examples/run-workflows.mdx @@ -0,0 +1,12 @@ +--- +title: Run Workflows +pcx_content_type: concept +sidebar: + order: 4 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO - show how to invoke a Workflow from an Agent + diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx new file mode 100644 index 000000000000000..bd0dd7cb7cfece7 --- /dev/null +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -0,0 +1,11 @@ +--- +title: Persist data +pcx_content_type: concept +sidebar: + order: 5 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO diff --git a/src/content/docs/agents/examples/self-host.mdx b/src/content/docs/agents/examples/self-host.mdx new file mode 100644 index 000000000000000..f20d91952b91252 --- /dev/null +++ b/src/content/docs/agents/examples/self-host.mdx @@ -0,0 +1,11 @@ +--- +title: Send Emails +pcx_content_type: concept +sidebar: + order: 100 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO - send emails diff --git a/src/content/docs/agents/examples/send-emails.mdx b/src/content/docs/agents/examples/send-emails.mdx new file mode 100644 index 000000000000000..76523af8ddbf85f --- /dev/null +++ b/src/content/docs/agents/examples/send-emails.mdx @@ -0,0 +1,11 @@ +--- +title: Schedule work +pcx_content_type: concept +sidebar: + order: 3 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO diff --git a/src/content/docs/agents/examples/testing-your-agents.mdx b/src/content/docs/agents/examples/testing-your-agents.mdx new file mode 100644 index 000000000000000..7435cdabccc0afd --- /dev/null +++ b/src/content/docs/agents/examples/testing-your-agents.mdx @@ -0,0 +1,11 @@ +--- +title: Asynchronous Workflows +pcx_content_type: concept +sidebar: + order: 11 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO diff --git a/src/content/docs/agents/examples/websockets.mdx b/src/content/docs/agents/examples/websockets.mdx new file mode 100644 index 000000000000000..6dd7f9c5ff2913f --- /dev/null +++ b/src/content/docs/agents/examples/websockets.mdx @@ -0,0 +1,11 @@ +--- +title: Send Emails +pcx_content_type: concept +sidebar: + order: 2 + +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +TODO - send emails diff --git a/src/content/docs/agents/getting-started/index.mdx b/src/content/docs/agents/getting-started/index.mdx new file mode 100644 index 000000000000000..0130d074d144e20 --- /dev/null +++ b/src/content/docs/agents/getting-started/index.mdx @@ -0,0 +1,13 @@ +--- +title: Getting started +pcx_content_type: navigation +sidebar: + order: 2 + group: + hideIndex: true + +--- + +import { DirectoryListing } from "~/components" + + diff --git a/src/content/docs/agents/getting-started/observing-agents.mdx b/src/content/docs/agents/getting-started/observing-agents.mdx new file mode 100644 index 000000000000000..f13e8f43bac290b --- /dev/null +++ b/src/content/docs/agents/getting-started/observing-agents.mdx @@ -0,0 +1,19 @@ +--- +title: Testing your Agent +updated: 2025-02-20 +sidebar: + order: 3 + +--- + +import { Render, PackageManagers, WranglerConfig } from "~/components" + +:::note + +New to building Agents and/or using Cloudflare Workers? This tutorial will guide you through the process of creating your first Agent and deploying it live. + +If you're familiar with Workers, you can head over to our [quick start guide](/agents/get-started/quick-start/) or review the [Agents API Reference](/agents/api/workers-api). + +::: + +TODO: testing \ No newline at end of file diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx new file mode 100644 index 000000000000000..d560fdac1915d53 --- /dev/null +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -0,0 +1,44 @@ +--- +title: Quick start +pcx_content_type: get-started +updated: 2025-02-20 +sidebar: + order: 10 + +--- + +import { Render, PackageManagers, WranglerConfig } from "~/components" + +:::note + +This quick-start guide will get you deploying your first Agent on Cloudflare in less than 5 minutes. + +If you're new to Cloudflare Workers, Agents, or Cloudflare in general, we recommend following the more comprehensive [Agents tutorial](/agents/get-started/tutorial/), which takes you through the process step-by-step. + +::: + +TODO: quick start. <= 5 steps. + +1. Use the template to create a new project +2. Open `src/index.ts` +3. Get familiar with it +4. Add some functionality (example) +5. Deploy it. + +## 1. Create your first Agent + + + +TODO: + +- what this template does +- how to deploy it and get quick win +- how to iterate on it and extend it +- re-deploy +- go explore :-) + +## 2. \ No newline at end of file diff --git a/src/content/docs/agents/getting-started/testing-your-agent.mdx b/src/content/docs/agents/getting-started/testing-your-agent.mdx new file mode 100644 index 000000000000000..8048bc6fa2e06fb --- /dev/null +++ b/src/content/docs/agents/getting-started/testing-your-agent.mdx @@ -0,0 +1,11 @@ +--- +title: Observing Agents +updated: 2025-02-20 +sidebar: + order: 2 + +--- + +import { Render, PackageManagers, WranglerConfig } from "~/components" + +TODO \ No newline at end of file diff --git a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx new file mode 100644 index 000000000000000..ada15d704c8fcd9 --- /dev/null +++ b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx @@ -0,0 +1,19 @@ +--- +title: Writing your first Agent +updated: 2025-02-20 +sidebar: + order: 1 + +--- + +import { Render, PackageManagers, WranglerConfig } from "~/components" + +:::note + +New to building Agents and/or using Cloudflare Workers? This tutorial will guide you through the process of creating your first Agent and deploying it live. + +If you're familiar with Workers, you can head over to our [quick start guide](/agents/get-started/quick-start/) or review the [Agents API Reference](/agents/api/workers-api). + +::: + +TODO: full beginner tutorial \ No newline at end of file diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index 35ce46fc36ae7bd..672aaa689b9dab4 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -1,5 +1,5 @@ --- -title: Build agents on Cloudflare +title: Build Agents on Cloudflare type: overview pcx_content_type: overview sidebar: @@ -15,6 +15,7 @@ import { Feature, LinkButton, LinkTitleCard, + PackageManagers, Plan, RelatedProduct, Render, @@ -22,15 +23,36 @@ import { Tabs, } from "~/components"; -Build AI-powered agents that can autonomously perform tasks, persist state, browse the web, and communicate back to users in real-time over any channel. +Build and deploy AI-powered agents that can autonomously perform tasks, persist state, browse the web, query data and communicate back to users in real-time over any channel. -- **Serverless inference that scales up _and_ down**: run AI directly on Cloudflre, without worrying about pre-provisioning VMs at peak, and worrying about utilization. Call the latest open-source models on [Workers AI](/workers-ai/), and pay just for what you use. -- **Non I/O bound pricing:** don't pay for long-running processes when your code is not executing. Cloudflare Workers is designed to scale down and [only charge you for CPU time](https://blog.cloudflare.com/workers-pricing-scale-to-zero/), as opposed to wall-clock time. -- **Designed for durable execution:** [Durable Objects](/durable-objects/) and [Workflows](/workflows) are built for a programming model that enables guaranteed execution for async tasks like long-running deep thinking LLM calls, human-in-the-loop, or unreliable API calls. -- **Scalable, and reliable, without compromising on performance:** by running on Cloudflare's network, agents can execute tasks close to the user without introducing latency for real-time experiences. +TODO: + +- "/agents is the docs for the agents platform" +- agents.cloudflare.com / agents.workers.dev (?) +- vibe check: need to signal on DO pricing + +## Why ship an Agent on Cloudflare? + +TODO - refine + +- **Batteries included**: Want your agent to search the web? Connect it to [Browser Rendering](/browser-rendering/). Store data? Write to the Agent's underlying [Durable Object](/workers/durable-objects/). Query your database? Connect it to your Postgres database [with Hyperdrive](/hyperdrive/). Stream data back in real-time to one, ten or one thousand users at once? Establish a [WebSocket](/workers/websockets/). Feed data to an AI model? Connect it to [Workers AI](/workers-ai/), OpenAI, Gemini, or Anthropic. +- **Scale to production**: Deploy agents to Cloudflare's global network and let them scale out automatically. +- **Don't break the bank**: Agents are built on Cloudflare Workers. Only pay when your agents are running. ## Start building + + + + +Head to the [Agents tutorial[(/getting-started/tutorial/) to dive into shipping your first Agent on Cloudflare. + +## Agents platform + diff --git a/src/content/docs/agents/products/ai-gateway.mdx b/src/content/docs/agents/products/ai-gateway.mdx deleted file mode 100644 index 152bb1879e435b4..000000000000000 --- a/src/content/docs/agents/products/ai-gateway.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -pcx_content_type: navigation -title: AI Gateway -external_link: /ai-gateway/ -sidebar: - order: 3 -head: [] -description: Observe and control your AI applications. ---- - - diff --git a/src/content/docs/agents/products/durable-objects.mdx b/src/content/docs/agents/products/durable-objects.mdx deleted file mode 100644 index 955c94ff44a712d..000000000000000 --- a/src/content/docs/agents/products/durable-objects.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -pcx_content_type: navigation -title: Durable Objects -external_link: /durable-objects/ -sidebar: - order: 6 -head: [] -description: Create collaborative applications, real-time chat, multiplayer games and more without needing to coordinate state or manage infrastructure. ---- - - diff --git a/src/content/docs/agents/products/email-workers.mdx b/src/content/docs/agents/products/email-workers.mdx deleted file mode 100644 index f2a3ccc62285ae3..000000000000000 --- a/src/content/docs/agents/products/email-workers.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -pcx_content_type: navigation -title: Email Workers -external_link: /email-routing/email-workers/ -sidebar: - order: 4 -head: [] -description: Implement any logic you need to process your emails and create complex rules ---- - - diff --git a/src/content/docs/agents/products/real-time.mdx b/src/content/docs/agents/products/real-time.mdx deleted file mode 100644 index 3d86980d7cc2e42..000000000000000 --- a/src/content/docs/agents/products/real-time.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -pcx_content_type: navigation -title: Real Time -external_link: /calls/ -sidebar: - order: 10 -head: [] -description: Build real-time serverless video, audio and data applications. ---- - - diff --git a/src/content/docs/agents/products/workers-ai.mdx b/src/content/docs/agents/products/workers-ai.mdx deleted file mode 100644 index fb54c8993df2406..000000000000000 --- a/src/content/docs/agents/products/workers-ai.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -pcx_content_type: navigation -title: Workers AI -external_link: /workers-ai/ -sidebar: - order: 2 -head: [] -description: Run machine learning models, powered by serverless GPUs, on Cloudflare's global network. ---- - - diff --git a/src/content/docs/agents/products/workflows.mdx b/src/content/docs/agents/products/workflows.mdx deleted file mode 100644 index eeb7aca8b0d2bcf..000000000000000 --- a/src/content/docs/agents/products/workflows.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -pcx_content_type: navigation -title: Workflows -external_link: /workflows/ -sidebar: - order: 5 -head: [] -description: Build durable multi-step applications on Cloudflare Workers with Workflows. ---- - - diff --git a/src/content/docs/agents/reference-architectures/index.mdx b/src/content/docs/agents/reference-architectures/index.mdx deleted file mode 100644 index e1dd3af47f3a47b..000000000000000 --- a/src/content/docs/agents/reference-architectures/index.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -pcx_content_type: reference -title: Reference Architectures -sidebar: - order: 1 - group: - hideIndex: true ---- - -import { DirectoryListing } from "~/components"; - -Example Reference Architectures - - diff --git a/src/content/docs/agents/reference-architectures/rag.mdx b/src/content/docs/agents/reference-architectures/rag.mdx deleted file mode 100644 index 7154404f2de6591..000000000000000 --- a/src/content/docs/agents/reference-architectures/rag.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -pcx_content_type: navigation -title: Retrieval Augmented Generation -external_link: /reference-architecture/diagrams/ai/ai-rag/ -sidebar: - order: 2 -head: [] -description: Build RAG architectures on Cloudflare ---- \ No newline at end of file diff --git a/src/content/docs/agents/reference-architectures/text-and-call.mdx b/src/content/docs/agents/reference-architectures/text-and-call.mdx deleted file mode 100644 index 5471f0d78645de3..000000000000000 --- a/src/content/docs/agents/reference-architectures/text-and-call.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -pcx_content_type: navigation -title: Send text messages from agents -external_link: /workflows/examples/twilio/ -sidebar: - order: 3 -head: [] -description: Send text messages and accept phone calls from your agent ---- \ No newline at end of file diff --git a/src/content/docs/agents/reference/agents-vs-workflows.mdx b/src/content/docs/agents/reference/agents-vs-workflows.mdx new file mode 100644 index 000000000000000..1edcde47e8c8922 --- /dev/null +++ b/src/content/docs/agents/reference/agents-vs-workflows.mdx @@ -0,0 +1,15 @@ +--- +title: Agents vs Workflows +pcx_content_type: concept +sidebar: + order: 2 +--- + +import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; + +When should build an Agent vs a Workflow? + +| Problem to Solve | Agent | Workflows | +|---|---|---| +| Row 1 Col 1 | Row 1 Col 2 | Row 1 Col 3 | +| Row 2 Col 1 | Row 2 Col 2 | Row 2 Col 3 | \ No newline at end of file diff --git a/src/content/docs/agents/products/index.mdx b/src/content/docs/agents/reference/index.mdx similarity index 71% rename from src/content/docs/agents/products/index.mdx rename to src/content/docs/agents/reference/index.mdx index 0fce7832787300d..77d033f1bfa25aa 100644 --- a/src/content/docs/agents/products/index.mdx +++ b/src/content/docs/agents/reference/index.mdx @@ -1,14 +1,14 @@ --- pcx_content_type: reference -title: Products +title: Reference sidebar: - order: 3 + order: 10 group: hideIndex: true --- import { DirectoryListing } from "~/components"; -Example Reference Architectures +Build AI Agents on Cloudflare From 63eaf7935a5a849bc71c3d4c1c53c7485dbba722 Mon Sep 17 00:00:00 2001 From: Rita Kozlov <2414910+rita3ko@users.noreply.github.com> Date: Sun, 23 Feb 2025 13:31:52 -0500 Subject: [PATCH 02/41] WIP - fixing typos (#20203) * add what are agents * update other files --- src/assets/images/agents/agent-workflow.svg | 7362 +++++++++++++++++ src/assets/images/agents/co-pilot.svg | 7356 ++++++++++++++++ .../images/agents/workflow-automation.png | Bin 0 -> 13316 bytes .../images/agents/workflow-automation.svg | 7348 ++++++++++++++++ .../docs/agents/concepts/calling-llms.mdx | 4 +- .../concepts/communcating-with-users.mdx | 4 +- .../docs/agents/concepts/what-are-agents.mdx | 62 +- .../docs/agents/concepts/workflows.mdx | 4 +- .../agents/getting-started/quick-start.mdx | 2 +- 9 files changed, 22130 insertions(+), 12 deletions(-) create mode 100644 src/assets/images/agents/agent-workflow.svg create mode 100644 src/assets/images/agents/co-pilot.svg create mode 100644 src/assets/images/agents/workflow-automation.png create mode 100644 src/assets/images/agents/workflow-automation.svg diff --git a/src/assets/images/agents/agent-workflow.svg b/src/assets/images/agents/agent-workflow.svg new file mode 100644 index 000000000000000..6370e454452a137 --- /dev/null +++ b/src/assets/images/agents/agent-workflow.svg @@ -0,0 +1,7362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/agents/co-pilot.svg b/src/assets/images/agents/co-pilot.svg new file mode 100644 index 000000000000000..acc6077c12bbb07 --- /dev/null +++ b/src/assets/images/agents/co-pilot.svg @@ -0,0 +1,7356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/agents/workflow-automation.png b/src/assets/images/agents/workflow-automation.png new file mode 100644 index 0000000000000000000000000000000000000000..50b0026e3e2d7bc3e181e5bd044b04bda3f46d1d GIT binary patch literal 13316 zcmeI3XH-*L*Y5$bOHrgq5fl-nh)Oeb3nEB4^b!cYNdRe~gn-yMih$Bv0HxOefrJi< z^xg@fD4isL5E3L1xbd9#dER)(xbJ($xcAE)_kIXjtn9V-+W)!M+<;IbXV1U(LoR2Q*y+80+U`*Sbd6pAM7@o38VBMl_L^_>dO07%~qYb9E zy2XYIggkO)n|Sf-7XR~Z2QHVn58r=3XBKes#(!OKzRf*z zLSX6a$^RGte|O^=`?tt}qe6t=?dHgoGbI)Ptc3-UhP@tCB}1N ze~+raPwH};rpwiS75i|y_G(PDO6EuT^ajZ6r0J5PwD(SczEdZeweH?W%YWXb3=n0W zpGj=~^7!fIKPa4(2@v+R88lAm^!!0QV$c6y>+x^R+B+S=o-adorgtiKX0Y)(y1K7F zTsA(Jl$6v##yDpXjtE|B^^14Bb5n_F!Yx#yeEcB5)|$HcrI9i}s>6rHKgv_Js7@<+?lgIRWhmtk=)cvTb-Pl`!3fPW7w~TCB0FMfp*DPCW!cD9| zqNQ=jJozfw@k%bLl}uRd+g#}sSb#!Ek+GI(p_#tUYE z3h*m%9}hydGzLi*4mCFxc4RNwLtWGCEG9tjw1O_868j4C%|)?%j|Vbc-pKGU4zRSj zi{+G!e_pjkG+=D48!i~T+E^Pq3~iM+$mrgZ1WP>>QD(zFb~YX!# z_9Ot!Oiq24gNF1|Li;q$pst^Fv*=C#zdDpQ)Nj6(pVjH^Ab)x&E7~x0Z7C80)n5*1 zVlEpFdGj&j9z)$*L#@SgQaT=DVMcu`Ip@?7f=u(3MMI|<+IF34LNaB{!YYxH*LhP}<`s z9s<9Nc|$opPJvMX$&i+61w+@jd^Ne%MQ&V3(1xPro2S?~#sO zRU5c@Q{fc-w9CBkYckyGe|L^v{3A5K!^0zRlzz?)oT2$u+w-0YZpXR?BMp3p#3Suy zT+rNpQ9F+r6xR}YDA$?GitgkX-Pjyj$UXOH@f}D^f17gYrf%I_d$_*5aeYD&_eb3P1V}bDPIv-zDyNzi#l0Mp0z8hL zj~pmKzPd;+0k3xEcIxY6NShV<@$*dWCBxnO%%{wMuM|=nU^f%G``g3iEE6-!*=r8J zSBBAA+k`Ry+sFR0+5?&e9%Q~h`dcOQe@J+`_Y%uJwf}1*1WBGyI@~8>s5`UP5sd>U zPyERs_eOx`Q+0%!YsV`uu+2+Sb1(7Vd#=`SqS&nbvf>^AiRAOB{s5LJqoifV{kUm!=L1+cbT@9(kibYI2#GWm4kt|=}*6$47Acy zCXGBga$L9AFty?;1}`M{21awW>^xuZ78MF&i!R3|%w|`W@SPoN@bG=;Q_PA&k2A9X zQQ%G!#6kC%wvL0w#lQs@Cor#D$%}IB`5%fYsJhcxXZRob*-baXpeV?i@~$(L;+IV3 zmb4hT)u_KQ;jfO>ubP&Du8m*SaI|(CD^54TPL_Sg5Kvf;-iPj39VFr|e`TSc!+Dfx zxE~9)C}neSQE#V~8(AkDb>}kHvx)jpe#N!8h7~^p;*bGP{k#WRs~UH>ozxl;&9_^L zYp-tFO+ec-Ok)T)P;;T@uW33Cyq4&4co-AjG&aZfZ9*IiJ*)g_K}P7hS@+$lyTkR+u4yvMOt zC78je zWZ9qd$ysF$(*67LIet3$>FaqCz0Ol(vhY+5FMT#F-w?OkvnRQ3)5K-NPK6AW{U0ro ziosWawZ5+SeSo~HOkPHaMWcyT!1q_0l`G61PQa^cWMwXuVpQx;cnr1GdMche<_SZ|zTl{F@6;cjG_7(9#7@=_;ixqiII<269UE6hnfv+UQrt>A zmwHpjE53(&*BLYmr3$Juyn`vr{+Lg0K`FzzJq~G+Zzw zAU8Uu#I5$}Ct1(wTG1`P@-DJTNv*84_(tPi(;_O5JSqj2Y6ol`=Gsr!?Jh|zFW-Xe znU+w3LO{bQqRv*D+;jW9PRj;IlORze0FvjyQu6-g@Eg7zvo!sI<9-OUJRF6n+LUFK zxBmq_6C{rCG4of!m91ZQxkmkB;+bHmurTmq%Y8JIy0V5o4DjS``0=GJ;nH-9qJg;_ z2J+R{SuN}p*CngP_$Q`EReyby=rCUL4K=FyB|}+hn1K4+fzRMi&%Ytb>L#j z;n&)X-GS(rsR^Y`2Ndw<=SMN>+*TvEwnGR;N1q`*7kE#53px)Pmps>}ju2g^s=f5s3;l2v-8Z^b6@>QwEHSS@ikDU^ zp=GCY;@z!aq*2NC4I*Z#7g0GrV13{X1vP;K=G!7A;i_Fb)KLGKK+`%wmBZ#E!=*oW zZ@=hhIY=L`QYrD#qMY`=YVAMm7YHIWjd*?S%3Z*`k~{im1xtycMX1ECpN?C`w%_qD z2sdxC0~F=4>$f&)ieBhT#0~R`VkNGYgeO!!EYvB+t)jBWFiQO=Sb7NA$ zt3!{a+)Q(1H`eP+mmA?@*MKeAnZ%r!zMQRbhZh!ygnEh4KMrPS z1K{Gi0(pXRRBOcirCS#X8lEG~g}Cu}w1yxxB;@D=1&hkyq0zGfXmyR#rig3>MEw@d zQU_>db-|B!DfnG2V%Yp}VZotbH-sSb%BLXg>${xCiA$nJl8~UvwXYnZS&L;ELbpkGq+(t}5GKLqUB$o^%VlPzc_}iZ`P!OR z)(0Qo)f{UuW@u@D6BQl2V2wg`6JztDOiRoyHWn;Pte~Ea$JV`;Jlr!L8ACpe?$TVm z3|e`$3q^QPG@o$ZcS6|D`-J0i?WsFa9Jv&sw(yIPrw81x7xIl^+0w(L{fsn|Z$ElH zLxyudR&sK~9>y=c>->zO*l@7F?xbq>n~o=(OxT8uk{LT|h$1lIRa3jNlS zokIpd<0c4@efTFJhWbV{eW0R$4HGH=-9X`x5o=c2d21_%z1&}db6gA=lnxNcY` zSz8Wof;2-i#&lu62itd@aJ8o37MzjlTR$$p@S2QYmOw@bs8+WN92?%y@T{F-cF~Qo zdV_4lLRNiq>_oV0;ZH6=e}Nag``zMmE!3xC1MY9@^iDOO8Ff& zUSB0A#1LA%;}p-nv6=v%BQI&kKMt1hWO}+0IREWao#82M&O05s4$zF<9)Q)jY>9h? zY*XoKVToRaya=W&?IzL`G4BWf7aBHg49*AD{`_PE;V*dWgRZ%t(bP8jaI~iSZTC$| zPEDznVMEL6xU%wv%+nGfR>e>JYqtymZ1)l8WwggL^RlLUQ_%~jW2`unqf`c#Y?$9h z#7!3p7NZ6ehfeCD<@{vF)9xrI7PLN!7BL4Eiz-~|K3SwyoAYGR-ZZSJ>w~H#)39T# zMN>MAtby@r7s#;2jE-7Sf9y`W9aeMNG!CF5=Uf(lb{B}vNE)YuwK_AB8Z3(+?+tU_ zG_y`w&%6-s<-vKa{>PWoYkoSYaW^ZZqCo_A=qJDB@3W?m@#AMtx!7yU?SAEmMz1Fc zjG}x>!YW{k)&aJ=Ub$w<3oN=e3S-Lf4PV{SN$0SS4vVX-4+x(gB1qjFKWcx5r)!%W z=-gla-T>8$z#iqc9H4CWP=YfdttO_g;(f(I{^I0)@}+*|@j6>^w#53TXgU z;cf`2=sQ}@;t0tshW`%6b`&|sbu*uhxZLk~R5COkT_gm6Fm0@ySL|fY9qzM(kGw+D zW>JUmj^!eHH<7wBRY=SMz-r%r%J$P~_eD1krO3K%wf9s)OpZ2*`C#3PwltQu`Rm9< z;8~obq7uzk(Lq;q8Na;c>?Y27tUmu-Xk4@vwz^-KU8U7|@zrpRd_pD4m1Shov0%J* zyhwL?4Xx07P_mxf=)MhqJs$;3lL|;WaoCNqjCfbOU;RiYc_Wy-lP+&)YT!RZ!g#uM3v$Dm4B|bhjCli zUp~xdt7x5L)317j`|9e?zny=|HJCXUd)1MHqSG>6BFNZf66auOYDLnhX>d_RIjye8 zKWA3%`j~xNekQ;Wdof-#&ssML{J7n;R&WDfEmBwZNxa|tvgEFKb3!}hCeyIHb2$iq zBOk2Sgsg}Va)OfIRr@;Jr(DY%O);??2bU1tS2k^t%J6XGs|gOVl)Fu6d(XY{+Y37I zX5Yyy4E$iu#%rcGI+l99dH`UGwVNd-4_@6A?DNa$Wet*=s|Uz}&`ny7>@%_i{8aowj!Nk~i-rw^cog z90EDIow`W2EY}I0Foj>8NOZG-6XZ&P+AeH+0Rni)!Hdjy@FEyE6>NaFJn`Qz6}7DNYot?P0hYS&4I&hKW00{zMw+=14fS zauo>Ij@uSJhCkqYU04%S()oEqzQ8gbZecZ1^nqs<U zPDU`^QO*yxJL80aIMcCXt3I&=KlaqL>*O49v>#FuV;@U+Jg-ciutzRugoa$>e(dyo zZPd@o?bDiTPx;qc?yTFB^|aUI+TnqYOxsFB#r;XVjYNx}G0ZLPr05uB$SvJ)e8bYl zntBdD;yFoE?8TU-1i=;>)+%H$4EAJyXzWhzm!`tXyk<*)eVRrlrH%T~W%gi3 zD8d#Y&lznu^EC>xbL@0sKTp{(rKfdfB(?!l$|Yg;eszAhtR0VkxSr8mww&ckBI%`_ zOK-ljma{z`yWLhDCj)MXlS?g({i2|*LBj$-eX+yfUI3dBYRA>l$SZ=e4{9z*2o8vS?ORUVE%l4unUUo~o#2CjSB>fQ@&&^kC!{I*if( zc!F+KALew9MrD@jrJvBZzd|D@j~>3dOb;JYG-)U^nb?<4k5%5&@Xe(QoNwvTgUeMK zxyqF9#$Xp~FRf}IfXe)M9U5V}3v*m5AY0zh)Kz6R0Lbeg1YfTtoRsMWy;h#Nt?x}^ zEreYc3mCQRAzIrejZ7o9-TQ8dv0JF7^8zeq8h&o){$qmmJ#t_ZkZhD^B33C3Pcgv{H(tZC2)U`C3OP-$(qlE>a$Iu~b9^Yw9Ts+JIKJQX|` z#D~*H7{#$RiCv`~Yjp5Vs?cyg0NIieZglmGWHD_Dwdn-rl31fcH zhto7{7Z(F`go*(dERC&WNi;80v;v>)B^w2$L1Yu;@9C{i!h2P0ASfD{277x~$X}AV zt-eT!S)1C_9Rj8qZY*YU%irjCoP{}~2{J99`TS2c6p-Hf3>;?DcQ81gunGWzz;*I? zTkG-*8|lvYj}xs!GhnF}ekl}p7DgG7xK4 zW=X@cqEIq@M;RD3p2^=+OWIUQ(Kj1@sjnXcX|wAxxbtyu1DH~zW-Nfm5-QT z@zQIOqD9lBK)S!0zWw`0G^cs?{1f^sxrotp&h1m0rw@XuUH%mVh@CZBZtuDC4?|tQ z;$lO0YJNO)(QAxQ>XTpJ^%yA4JL^!*%msQL@n04el6zjs-wO|X@SG0DGcccGrm4kv zqK>}1&(xBC3FFA={hNkiS7{Fpmo0)cTpPbZ^w3Rd}lLe~B=EjhOELKVs;Hu^Lm@Q1|q< z6Cme4t8%{EX2^EP{=A@bv91IFfF*W2J#y<7MTttE;(jUM)E3NX$Zy& zMv(fu1OgX6V3wsUK|_0k(IIiu{f@q|EpuGY)+fGtrO>Ch*TQFOT-9*S}<0zU&Of5KeO$)Qk@bQCB?p&K8;kTUMOyTn-wC)>XWU;BvJ7`DFvrlZ>nIdJJmZp93Et z`l7w%QWId3ig^A4|CQaKcd?QFq!iC3YR75ygW)?WHRg=^n#V`7Yn8jw?+@s)+Wk@DO5Qibw%UAn7pc&F?fqLUg|1eIL2qQdM(TO ziURuS>Vhrw=`H$v3U`j`zh2Y|Jcvt&hTda}`p%gBT@8oOiBr6BZ=)JkX9Abun2m!z z?uy4D8|S*8crIT1>Fq3~D4Hto58A6{2IPa<1(k47S>DcLin_U~06?;&`%xCp`duf- zKepO=0q)DpK1Ap?WGcD$w1~rV)KmRCVMiUW=;t0W*dG3~7zYkUx4RSL*7_M_FaQM5gnq@`XU~#eg4Sgg=F&dQx$6 z#~Y<)W){Bz1+|xJ4oQ{~Eh$le;ala>R$fuCe!nSS2c&b8pp4n{ArVtp)u{!}`9efEn>JK6G z^wGp_i0S1Ef-`>`>TDr@v-{oX%olSqzkj>v&r|H88r0nfN`O~vpBGP2H1=j+FbdMh zG0Ov(d7Jp&OL(yxsp!$~Ynr*D)ZJ+i^FoB$RC}l>(C1&bnII&prklInbL+jZcc)0= zg05A$N4)W@uHu>@#!ydrv{Z|#U*}Em9i24r;!i-796htd-u2l)^%GC+lpwU;0SfIR1cLl$kN`IyT|*x_g07z+6x1F&%WZh7Cr0-jDzOu7e{+Bs)yW% z5>f|WPD@o5>0?z~e$wJKULie8z`hu(Tjc$o&5Ca=5F?xon1ScL|Z>fa3^o<(K9Lc%M+wazp2?*-Rgd0JOq~plpPXRoBD1vNHBkC z)1M#Sd4S54%W#?I{NvoAUDMW)lEdKHuLhdhSBfN&;)q0Xzg^Fb<}U0J{$iQHc=J2;zM{7s#itYPx?QdN zb23Sdx_t_RDL%Hk@vGg}%Zj3x>XTX=6k1DgCJkI_6K^b|bkPp5p|Q4);u|VWz`$8O zfWa7BX9GnjJm2)N*!@;{=B4;I@j93kBEqIUrb_e%u85MEU6N)kvS|_%i^wjT#bs;` zH!>-R0L)A@(l-x6bBlI4N0yFFPgLRX!4|m=u^PyrL@51B2&SIV6o2CYh$xT zV4RoF!a~wd4fW#sjr-*r-Y6s8sLIIku2$60;GMVHJ%Q2jtD^n3`E2aYOT(6Dz5 zOJ6Lyp_r?9z99xM^@LbCtlK^6_bSw~li$8K>u6G=d#ZnA!B3bp40%@Eneic^&Rzi` zde4t1&rUg4v11HpdKmHf71=#X5K1UFAj#dB9+Zfx$<{vh_uFfx6SLEUflQ9#(wmc= zv-~FZuA<%m4h1i4Cx%~i7>_ar03cfG;SIo=kSOzpgHw4@vn6b&k_e~jm2q?3T#oj} z4tBfh)R3LXasZ4sRV9TlRj^JB4D6O?eKP#~h20)m_z40y^1-U(gUs=srT*>hpKmUT z40@5q`HdCV(L;k-Vh8r7T@4_44F7)NZdEzuR$x>img&?YUMuhe0{nHo+7BPmi^QGv zk00i7zfl`6&{htTkTJ!@#`I=Xxiw7>PQXH|5Z=ajUsR_wwz&tj4d61m#+LdBNVCM= zaxfyvArzO0D`UvdZ&CS=doE>uA|SJZ7ztjvFW41DqjOWc91pBo$-1%r=X3h$J#xv{9LhiiZg-nFRry~YZ7`jVYKuxVtpi^{1UKk zD|JKryDH`-<`sZkTWfuWcSO`@tDfJ@LOW+()kH3LRuVB0{izf!l`2?ObR|Iy(f?`8 z`hr1)il!W_(^&I!#pL@VZm@FkZ(MOk@dA*>X#s)>V%au`>zjG#T6w0&ynJdROP5MR zB-w}YGv#K-7}LkXic|YJS&FZ@z8S5?u>HLv&F2WSIL-oT9po3Z%0afvo%sX+DxAgR z;AyV#_wm7Mwv=hqQvJ5Vrhk#}Vp2%3ReTWX?mRblB(}}GSiJ3PT5d@4c|3VHJ;?)Ritz1W`a{Mx zce_j*?R2iXm#C6mbj#l#y_B0bk4uf=!DWT;-iH=3BZy+hy_jUU_#HFN3=dwkS(z7Lt}|He{_5bP zyU;u#eC$?3!9sG2sD{FlWj6V9sfmg59J~FeTFIQ-x2T0B0CWmBpv%sgHB$hoGTDfW znRj4(Ao1fYU)?Eux4EhV2W7%j)UH4Jv8f}cHjfl(cwO7fs%2^te%>>*F(j26c|<^( ztHK(eN_$cq`dO09h0e`?$FeKBSwnII$J+x61!7?}Ws6 zD_)k7_YP7P6+ptgj4GaKRYVn}rCA?Ve~4<08NFn+cVlAgB9>ST2F2w;Bs5VQ58|^t zYRgL|(Hr2wF~cTLCt;`iV~1u?Na9@uIS`gtPj%f);Cdie{#)eHK$AXjcWD2w9&aG3 z+ZtQct^V!Ag>KeOys2#*)D<-c@OiiCDwDPoj#TBt)QzL!tuU3F`(0@@yBW_%G|d-# zyav4BKSyMvkKcEE=;2S6C^1*Np89-?m4mk>I#Bse?sVF&p$BaPc? zROa~4Uiq1>5XZjM-HB{I`^%#0{YmXf`Fdn|yfMgg9gg)zZB)%x9NRRBvDPyj3ZWDLi~)7&UdlIc<=Yb)mR06jwBD`&QP2c&Tn6qdczV>T$C* zibK%cM>$8;@*OL}WK~^OXd|l>f)*4fzYyHdq@s8HwEf)rz~asZuo&T@X7za)zTthS zs3jFx>C$igwxTu|S~#4xWPeC1KlsB4R0rwj>z3ti6u91vY6U{FdS_-&p%GZlXbubE2kH5_vGy+c?&M?niyCPO^;zOsWi2@G1%V^0~_&|SxS9Fr} z#{(FJDqlP)d?e(Iw=QWA_<~ysl$Oz42PkOaMWnGRTlg#`J1?@qEMAL z=r)O~cA3$=;djo%RjtRC?uR|wmPu?a+8dHr?u7W6)7CyO3 zz?(!IGFwjO20k__qJ&_&;ZY{Omy3{#-upU7R^oEUY-IQjb(%=j8mo@T=h!KB845Z` z;rc0l_(|f&kOBb#D$KE#zRR)i8&s% zpySF}XHj-ciOnrnekITUr|?`i!rH%%S=Y-2PJ9o4$)8<*?q)bL^@Y+HtB#?4+uf)P z73lq#`I3HZ-r;M@pK&v(VA$2Z&6yw5c4z+b!8bunSX5*BS($f^rn$oVGZpg^qemVLrW}wG2`OwS%sIA*`D+L?>80ntb-NSN>aqKNI9TByGfsthADf*5- zx}rAl{=_L+dJZWQPs?;QbWZo8kK+h^pjBSJHbT!a2aIS^=)eQpSm>ekgJ0>dX`Ts0 zShm$a*p2b89UC&SzhJCttkr^Ty=K3u9_%0H*rztD(^BlI@9(oI1dJ6A>4d8>{k{*u zh5xTzCZ1p@aq&&b;SOn$wsFNTmIL#=P2Z-OUW{jIB4J}zaq + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/content/docs/agents/concepts/calling-llms.mdx b/src/content/docs/agents/concepts/calling-llms.mdx index 84cf31bc4217f53..3697898e36c42e5 100644 --- a/src/content/docs/agents/concepts/calling-llms.mdx +++ b/src/content/docs/agents/concepts/calling-llms.mdx @@ -1,8 +1,8 @@ --- -title: Communicating with users +title: Calling LLMs pcx_content_type: concept sidebar: - order: 4 + order: 5 --- diff --git a/src/content/docs/agents/concepts/communcating-with-users.mdx b/src/content/docs/agents/concepts/communcating-with-users.mdx index 00f048f7f045c06..53f7945fbe1b704 100644 --- a/src/content/docs/agents/concepts/communcating-with-users.mdx +++ b/src/content/docs/agents/concepts/communcating-with-users.mdx @@ -1,8 +1,8 @@ --- -title: Calling LLMs +title: Human in the Loop pcx_content_type: concept sidebar: - order: 3 + order: 4 --- diff --git a/src/content/docs/agents/concepts/what-are-agents.mdx b/src/content/docs/agents/concepts/what-are-agents.mdx index f4491215cbe2877..47a8b1617f22f43 100644 --- a/src/content/docs/agents/concepts/what-are-agents.mdx +++ b/src/content/docs/agents/concepts/what-are-agents.mdx @@ -1,14 +1,66 @@ --- -title: Workflows +title: What are Agents? pcx_content_type: concept sidebar: - order: 1 + order: 2 --- import { Render } from "~/components"; -TODO - what are agents? +### What is an agent? +An agent is an AI system that can autonomously execute tasks by making decisions about tool usage and process flow. Unlike traditional automation that follows predefined paths, agents can dynamically adapt their approach based on context and intermediate results. Agents are also distinct from co-pilots (e.g. traditional chat applications) in that they can fully automate a task, as opposed to simply augmenting and extending human input. -- terminology -- diagram: orchestrator / container / task / workflow +- **Agents** → non-linear, non-deterministic (can change from run to run) +- **Workflows** → linear, deterministic execution paths +- **Co-pilots** → augmentative AI assistance requiring human intervention + +### Example: Booking Vacations +If this is your first time working with, or interacting with agents, this example will illustrate how an agent works within a context like booking a vacation. If you're already familiar with the topic, read on. + +Imagine you're trying to book a vacation. You need to research flights, find hotels, check restaurant reviews, and keep track of your budget. + +##### Traditional Workflow Automation +A traditional automation system follows a predetermined sequence: +- Takes specific inputs (dates, location, budget) +- Calls predefined API endpoints in a fixed order +- Returns results based on hardcoded criteria +- Cannot adapt if unexpected situations arise + +![Traditional workflow automation diagram](~/assets/images/agents/workflow-automation.svg) + +##### AI Co-pilot +A co-pilot acts as an intelligent assistant that: + +- Provides hotel and itinerary recommendations based on your preferences +- Can understand and respond to natural language queries +- Offers guidance and suggestions +- Requires human decision-making and action for execution + +![A co-pilot diagram](~/assets/images/agents/co-pilot.svg) + +##### Agent +An agent combines AI's ability to make judgements and call the relevant tools to execute the task. An agent's output will be nondeterministic given: + +- Real-time availability and pricing changes +- Dynamic prioritization of constraints +- Ability to recover from failures +- Adaptive decision-making based on intermediate results + +![An agent diagram](~/assets/images/agents/agent-workflow.svg) + +An agents can dynamically generate and itinerary and execute on booking reservations, similarly to what you would expect from a travel agent. + +### Three primary components of agent systems: + +- **Decision Engine**: Usually an LLM (Large Language Model) that determines action steps +- **Tool Integration**: APIs, functions, and services the agent can utilize +- **Memory System**: Maintains context and tracks task progress + +#### How Agents Work + +Agents operate in a continuous loop of: +1. **Observing** the current state or task +2. **Planning** what actions to take, using AI for reasoning +3. **Executing** those actions using available tools (often APIs or [MCPs](https://modelcontextprotocol.io/introduction)) +4. **Learning** from the results (storing results in memory, updating task progress, and preparing for next iteration) diff --git a/src/content/docs/agents/concepts/workflows.mdx b/src/content/docs/agents/concepts/workflows.mdx index 37cebb9623ed7c9..2c2029eda5d36dc 100644 --- a/src/content/docs/agents/concepts/workflows.mdx +++ b/src/content/docs/agents/concepts/workflows.mdx @@ -1,8 +1,8 @@ --- -title: What are Agents +title: Workflows pcx_content_type: concept sidebar: - order: 2 + order: 3 --- diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index d560fdac1915d53..a3cdfaf34c5216c 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -17,7 +17,7 @@ If you're new to Cloudflare Workers, Agents, or Cloudflare in general, we recomm ::: -TODO: quick start. <= 5 steps. +TODO: quick start 1. Use the template to create a new project 2. Open `src/index.ts` From eee05309ebed87972fe2b3313f37d7788707406b Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sun, 23 Feb 2025 14:43:32 -0500 Subject: [PATCH 03/41] onward --- .../concepts/communcating-with-users.mdx | 11 --- .../docs/agents/examples/ask-ai-models.mdx | 11 --- .../docs/agents/examples/browse-the-web.mdx | 6 +- src/content/docs/agents/examples/evals.mdx | 4 +- .../agents/examples/manage-and-sync-state.mdx | 81 +++++++++++++++++++ .../docs/agents/examples/persist-data.mdx | 11 --- src/content/docs/agents/examples/rag.mdx | 4 +- .../docs/agents/examples/run-workflows.mdx | 3 +- .../docs/agents/examples/schedule-tasks.mdx | 60 +++++++++++++- .../docs/agents/examples/self-host.mdx | 6 +- .../docs/agents/examples/send-emails.mdx | 4 +- .../agents/examples/testing-your-agents.mdx | 4 +- .../docs/agents/examples/using-ai-models.mdx | 61 ++++++++++++++ .../docs/agents/examples/websockets.mdx | 6 +- .../agents/getting-started/quick-start.mdx | 57 ++++++++++++- 15 files changed, 270 insertions(+), 59 deletions(-) delete mode 100644 src/content/docs/agents/concepts/communcating-with-users.mdx delete mode 100644 src/content/docs/agents/examples/ask-ai-models.mdx create mode 100644 src/content/docs/agents/examples/manage-and-sync-state.mdx delete mode 100644 src/content/docs/agents/examples/persist-data.mdx create mode 100644 src/content/docs/agents/examples/using-ai-models.mdx diff --git a/src/content/docs/agents/concepts/communcating-with-users.mdx b/src/content/docs/agents/concepts/communcating-with-users.mdx deleted file mode 100644 index 53f7945fbe1b704..000000000000000 --- a/src/content/docs/agents/concepts/communcating-with-users.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Human in the Loop -pcx_content_type: concept -sidebar: - order: 4 - ---- - -import { Render } from "~/components"; - -calling LLMs \ No newline at end of file diff --git a/src/content/docs/agents/examples/ask-ai-models.mdx b/src/content/docs/agents/examples/ask-ai-models.mdx deleted file mode 100644 index 60ce09fee41e29c..000000000000000 --- a/src/content/docs/agents/examples/ask-ai-models.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Asynchronous Workflows -pcx_content_type: concept -sidebar: - order: 7 - ---- - -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; - -TODO diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/examples/browse-the-web.mdx index 0739d352fa96527..3a924bc93d3b4a2 100644 --- a/src/content/docs/agents/examples/browse-the-web.mdx +++ b/src/content/docs/agents/examples/browse-the-web.mdx @@ -1,10 +1,10 @@ --- -title: Self-hosting Agents +title: Browse the web pcx_content_type: concept sidebar: order: 99 --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -TODO - send emails +TODO diff --git a/src/content/docs/agents/examples/evals.mdx b/src/content/docs/agents/examples/evals.mdx index a4be57bc6a0b112..b6d7d27c727e7d2 100644 --- a/src/content/docs/agents/examples/evals.mdx +++ b/src/content/docs/agents/examples/evals.mdx @@ -1,11 +1,11 @@ --- -title: Asynchronous Workflows +title: Evals pcx_content_type: concept sidebar: order: 15 --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; TODO diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx new file mode 100644 index 000000000000000..5b04d9ca3efe42e --- /dev/null +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -0,0 +1,81 @@ +--- +title: Manage and sync state +pcx_content_type: concept +sidebar: + order: 6 +--- + +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; + +Every Agent has built-in state management capabilities, including built-in storage and synchronization between the Agent and frontend applications. State within an Agent is: + +* Persisted across Agent restarts: data is permanently persisted within the Agent. +* Automatically serialized/deserialized: you can store any JSON-serializable data. +* Immediately consistent within the Agent: read your own writes. +* Thread-safe for concurrent updates + +### State management + +Every agent has built-in state management capabilities. You can set and update the agent's state directly using `this.state`: + + + +```ts +import { Agent } from "@cloudflare/agents"; + +export class MyAgent extends Agent { + // Update state in response to events + async incrementCounter() { + this.setState({ + ...this.state, + counter: this.state.counter + 1, + }); + } + + // Handle incoming messages + async onMessage(message) { + if (message.type === "update") { + this.setState({ + ...this.state, + ...message.data, + }); + } + } + + // Handle state updates + onStateUpdate(state, source: "server" | Connection) { + console.log("state updated", state); + } +} +``` + + + +### Synchronizing state + +Clients can connect to an Agent and stay synchronized with its state using the React hooks provided as part of `@cloudflare/agents/react`: + + + +```ts + + +``` + + + + +The state synchronization system: + +* Automatically syncs the agent's state to all connected clients +* Handles client disconnections and reconnections gracefully +* Provides immediate local updates +* Supports multiple simultaneous client connections + +Common use cases: + +* Real-time collaborative features +* Multi-window/tab synchronization +* Live updates across multiple devices +* Maintaining consistent UI state across clients +* When new clients connect, they automatically receive the current state from the agent, ensuring all clients start with the latest data. \ No newline at end of file diff --git a/src/content/docs/agents/examples/persist-data.mdx b/src/content/docs/agents/examples/persist-data.mdx deleted file mode 100644 index f87a18d642f6871..000000000000000 --- a/src/content/docs/agents/examples/persist-data.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Retrieval Augmented Generation -pcx_content_type: concept -sidebar: - order: 6 - ---- - -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; - -TODO diff --git a/src/content/docs/agents/examples/rag.mdx b/src/content/docs/agents/examples/rag.mdx index 60ce09fee41e29c..d488a6fa3bf802b 100644 --- a/src/content/docs/agents/examples/rag.mdx +++ b/src/content/docs/agents/examples/rag.mdx @@ -1,11 +1,11 @@ --- -title: Asynchronous Workflows +title: Retrieval Augmented Generation pcx_content_type: concept sidebar: order: 7 --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; TODO diff --git a/src/content/docs/agents/examples/run-workflows.mdx b/src/content/docs/agents/examples/run-workflows.mdx index 316d622e4d4f448..b2c86d98a3a9d7f 100644 --- a/src/content/docs/agents/examples/run-workflows.mdx +++ b/src/content/docs/agents/examples/run-workflows.mdx @@ -6,7 +6,6 @@ sidebar: --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; TODO - show how to invoke a Workflow from an Agent - diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index bd0dd7cb7cfece7..0dd47e9a7d8b3c9 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -1,11 +1,65 @@ --- -title: Persist data +title: Schedule tasks pcx_content_type: concept sidebar: order: 5 --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -TODO +An Agent can schedule tasks to be run in the future by calling `this.schedule(when, callback, data)`, where `when` can be a delay, a `Date`, or a cron string; callback the function name to call, and data is an object of data to pass to the function. + +### Scheduling tasks + +You can call `this.schedule` within any method on an Agent: + + + +```ts +// schedule a task to run in 10 seconds +this.schedule(10, "myTask", { message: "hello" }); + +// schedule a task to run at a specific date +this.schedule(new Date("2025-01-01"), "myTask", { message: "hello" }); + +// schedule a task to run every 10 seconds +this.schedule("*/10 * * * *", "myTask", { message: "hello" }); + +// schedule a task to run every 10 seconds, but only on Mondays +let task = await this.schedule("0 0 * * 1", "myTask", { message: "hello" }); + +// cancel a scheduled task +this.cancelSchedule(task.id); +``` + + + + +### Managing scheduled tasks + +You can get, cancel and filter across scheduled tasks within an Agent using the scheduling API: + + + +```ts +// Get a specific schedule by ID +let task = await this.getSchedule(task.id) + +// Get all scheduled tasks +let tasks = await this.getScheduledTasks(); + +// Cancel a task by its ID +await this.cancelSchedule(task.id); + +// Filter for specific tasks +// e.g. all tasks starting in the next hour +let tasks = this.getSchedules({ // returns an iterator + timeRange: { + start: new Date(Date.now()), + end: new Date(Date.now() + 60 * 60 * 1000), + }, +); +``` + + diff --git a/src/content/docs/agents/examples/self-host.mdx b/src/content/docs/agents/examples/self-host.mdx index f20d91952b91252..760509c3a6ca454 100644 --- a/src/content/docs/agents/examples/self-host.mdx +++ b/src/content/docs/agents/examples/self-host.mdx @@ -1,11 +1,11 @@ --- -title: Send Emails +title: Self-hosting Agents pcx_content_type: concept sidebar: order: 100 --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -TODO - send emails +TODO diff --git a/src/content/docs/agents/examples/send-emails.mdx b/src/content/docs/agents/examples/send-emails.mdx index 76523af8ddbf85f..d3e68647963a695 100644 --- a/src/content/docs/agents/examples/send-emails.mdx +++ b/src/content/docs/agents/examples/send-emails.mdx @@ -1,11 +1,11 @@ --- -title: Schedule work +title: Send emails pcx_content_type: concept sidebar: order: 3 --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; TODO diff --git a/src/content/docs/agents/examples/testing-your-agents.mdx b/src/content/docs/agents/examples/testing-your-agents.mdx index 7435cdabccc0afd..3533b30d810b06f 100644 --- a/src/content/docs/agents/examples/testing-your-agents.mdx +++ b/src/content/docs/agents/examples/testing-your-agents.mdx @@ -1,11 +1,11 @@ --- -title: Asynchronous Workflows +title: Testing Agents pcx_content_type: concept sidebar: order: 11 --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; TODO diff --git a/src/content/docs/agents/examples/using-ai-models.mdx b/src/content/docs/agents/examples/using-ai-models.mdx new file mode 100644 index 000000000000000..3db4d39bcaf5948 --- /dev/null +++ b/src/content/docs/agents/examples/using-ai-models.mdx @@ -0,0 +1,61 @@ +--- +title: Using AI Models +pcx_content_type: concept +sidebar: + order: 7 + +--- + +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; + +Agents can communicate with AI models hosted on any provider, including [Workers AI](/workers-ai/), OpenAI, Anthropic and Google's Gemini. + +Because Agents are built on top of [Durable Objects](/durable-objects/), each agent or chat session is associated with a stateful compute instance. Tradtional serverless architectures often present challenges for persistent connections needed in real-time applications like chat. + +A user can disconnect during a long-running response from a modern reasoning model (such as `o3-mini` or DeepSeek R1), or lose conversational context when refreshing the browser. Instead of relying on request-response patterns and managing an external database to track & store conversation state, state can be stored directly within the Agent. If a client disconnects, the Agent can write to its own distributed storage, and catch the client up as soon as it reconnects: even if it's hours or days later. + +## Calling AI Models + +### Workers AI + +TODO + +- Workers AI +- AI Gateway / model routing + + +### AI SDK + +The [AI SDK](https://sdk.vercel.ai/docs/introduction) provides a unified API for using AI models, including for text generation, tool calling, structured responses, image generation, and more. + + + +```ts +import { Agent } from "@cloudflare/agents" +import { generateText } from 'ai'; +import { openai } from '@ai-sdk/openai'; + +export class MyAgent extends Agent { + constructor(state: DurableObjectState, env: Env) { + super(state, env); + } + + async onRequest(request: Request): Promise { + const { text } = await generateText({ + model: openai("o3-mini"), + prompt: "Build me an AI agent on Cloudflare Workers", + }); + + return Response.json({modelResponse: text}) + } +} +``` + + + +### OpenAI SDK + + +## Long-running LLM calls + +TODO \ No newline at end of file diff --git a/src/content/docs/agents/examples/websockets.mdx b/src/content/docs/agents/examples/websockets.mdx index 6dd7f9c5ff2913f..40114ee5c4e87e4 100644 --- a/src/content/docs/agents/examples/websockets.mdx +++ b/src/content/docs/agents/examples/websockets.mdx @@ -1,11 +1,11 @@ --- -title: Send Emails +title: Real-time and WebSockets pcx_content_type: concept sidebar: order: 2 --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -TODO - send emails +TODO diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index a3cdfaf34c5216c..2910354b42c77ad 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -7,11 +7,11 @@ sidebar: --- -import { Render, PackageManagers, WranglerConfig } from "~/components" +import { Render, PackageManagers, TypeScriptExample, WranglerConfig } from "~/components" :::note -This quick-start guide will get you deploying your first Agent on Cloudflare in less than 5 minutes. +**This quick-start guide will get you deploying your first Agent on Cloudflare in less than 5 minutes.** If you're new to Cloudflare Workers, Agents, or Cloudflare in general, we recommend following the more comprehensive [Agents tutorial](/agents/get-started/tutorial/), which takes you through the process step-by-step. @@ -25,7 +25,12 @@ TODO: quick start 4. Add some functionality (example) 5. Deploy it. -## 1. Create your first Agent +## Prerequisites + + + +## 1. Create an Agents project + + +```ts +import { Agent } from "@cloudflare/agents"; + +export class MyAgent extends Agent { + async onRequest(request) { + // Code that your Agent runs on a request + }, + + + async schedule(when, callback, payload) { + // Code that your Agent runs on a schedule + }, + + + + +} +``` + + + +## 3. Deploy your Agent + +Agents are deployed just like any other Workers application: + +```sh +npx wrangler@latest deploy +``` +```sh output +TODO +``` + +## 4. Run your Agent + +TODO + +## 5. Build out your Agent + +TODO From 84eef5fc84bca0fcd2fa1c1578c6308816a42d63 Mon Sep 17 00:00:00 2001 From: Rita Kozlov Date: Sun, 23 Feb 2025 15:24:38 -0500 Subject: [PATCH 04/41] add tools and human loop images --- src/assets/images/agents/agent-workflow.svg | 71 +- .../images/agents/human-in-the-loop.svg | 7367 +++++++++++++++++ .../docs/agents/concepts/calling-llms.mdx | 24 +- .../agents/concepts/human-in-the-loop.mdx | 53 + src/content/docs/agents/concepts/tools.mdx | 45 + .../docs/agents/concepts/what-are-agents.mdx | 4 +- .../docs/agents/concepts/workflows.mdx | 23 +- 7 files changed, 7545 insertions(+), 42 deletions(-) create mode 100644 src/assets/images/agents/human-in-the-loop.svg create mode 100644 src/content/docs/agents/concepts/human-in-the-loop.mdx create mode 100644 src/content/docs/agents/concepts/tools.mdx diff --git a/src/assets/images/agents/agent-workflow.svg b/src/assets/images/agents/agent-workflow.svg index 6370e454452a137..82ccd7f92120e1c 100644 --- a/src/assets/images/agents/agent-workflow.svg +++ b/src/assets/images/agents/agent-workflow.svg @@ -1,6 +1,6 @@ - - - + + + @@ -7323,40 +7323,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + diff --git a/src/assets/images/agents/human-in-the-loop.svg b/src/assets/images/agents/human-in-the-loop.svg new file mode 100644 index 000000000000000..96a8fe98234916d --- /dev/null +++ b/src/assets/images/agents/human-in-the-loop.svg @@ -0,0 +1,7367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/content/docs/agents/concepts/calling-llms.mdx b/src/content/docs/agents/concepts/calling-llms.mdx index 3697898e36c42e5..855f8bef8b410c5 100644 --- a/src/content/docs/agents/concepts/calling-llms.mdx +++ b/src/content/docs/agents/concepts/calling-llms.mdx @@ -2,10 +2,30 @@ title: Calling LLMs pcx_content_type: concept sidebar: - order: 5 + order: 6 --- import { Render } from "~/components"; -calling LLMs \ No newline at end of file +### Understanding LLM Providers and Model Types + +Different LLM providers offer models optimized for specific types of tasks. When building AI systems, choosing the right model is crucial for both performance and cost efficiency. + +#### Reasoning Models +Models like OpenAI's o1, Anthropic's Claude, and DeepSeek's R1 are particularly well-suited for complex reasoning tasks. These models excel at: +- Breaking down problems into steps +- Following complex instructions +- Maintaining context across long conversations +- Generating code and technical content + +For example, when implementing a travel booking system, you might use a reasoning model to analyze travel requirements and generate appropriate booking strategies. + +#### Instruction Models +Models like GPT-4 and Claude Instant are optimized for following straightforward instructions efficiently. They work well for: +- Content generation +- Simple classification tasks +- Basic question answering +- Text transformation + +These models are often more cost-effective for straightforward tasks that don't require complex reasoning. \ No newline at end of file diff --git a/src/content/docs/agents/concepts/human-in-the-loop.mdx b/src/content/docs/agents/concepts/human-in-the-loop.mdx new file mode 100644 index 000000000000000..11e14e496bfe4ef --- /dev/null +++ b/src/content/docs/agents/concepts/human-in-the-loop.mdx @@ -0,0 +1,53 @@ +--- +title: Human in the Loop +pcx_content_type: concept +sidebar: + order: 5 + +--- + +import { Render, Note, Aside } from "~/components"; + +### What is Human-in-the-Loop? + +Human-in-the-Loop (HITL) workflows integrate human judgment and oversight into automated processes. These workflows pause at critical points for human review, validation, or decision-making before proceeding. This approach combines the efficiency of automation with human expertise and oversight where it matters most. + +![A human-in-the-loop diagram](~/assets/images/agents/human-in-the-loop.svg) + +#### Understanding Human-in-the-Loop Workflows + +In a Human-in-the-Loop workflow, processes aren't fully automated. Instead, they include designated checkpoints where human intervention is required. For example, in a travel booking system, a human may want to confirm the travel before an agent follows through with a transaction. The workflow manages this interaction, ensuring that: + +1. The process pauses at appropriate review points +2. Human reviewers receive necessary context +3. The system maintains state during the review period +4. Review decisions are properly incorporated +5. The process continues once approval is receive + +### Best Practices for Human-in-the-Loop Workflows + +#### Long-Term State Persistence + +Human review processes don't operate on predictable timelines. A reviewer might need days or weeks to make a decision, especially for complex cases requiring additional investigation or multiple approvals. Your system needs to maintain perfect state consistency throughout this period, including: +- The original request and context +- All intermediate decisions and actions +- Any partial progress or temporary states +- Review history and feedback + + + +#### Continuous Improvement Through Evals + +Human reviewers play a crucial role in evaluating and improving LLM performance. Implement a systematic evaluation process where human feedback is collected not just on the final output, but on the LLM's decision-making process. This can include: + +- Decision Quality Assessment: Have reviewers evaluate the LLM's reasoning process and decision points, not just the final output. +- Edge Case Identification: Use human expertise to identify scenarios where the LLM's performance could be improved. +- Feedback Collection: Gather structured feedback that can be used to fine-tune the LLM or adjust the workflow. [AI Gateway](https://developers.cloudflare.com/ai-gateway/evaluations/add-human-feedback/) can be a useful tool for setting up an LLM feedback loop. + +#### Error Handling and Recovery + +Robust error handling is essential for maintaining workflow integrity. Your system should gracefully handle various failure scenarios, including reviewer unavailability, system outages, or conflicting reviews. Implement clear escalation paths for handling exceptional cases that fall outside normal parameters. + +The system should maintain stability during paused states, ensuring that no work is lost even during extended review periods. Consider implementing automatic checkpointing that allows workflows to be resumed from the last stable state after any interruption. diff --git a/src/content/docs/agents/concepts/tools.mdx b/src/content/docs/agents/concepts/tools.mdx new file mode 100644 index 000000000000000..424b123d51b3c59 --- /dev/null +++ b/src/content/docs/agents/concepts/tools.mdx @@ -0,0 +1,45 @@ +--- +title: Tools +pcx_content_type: concept +sidebar: + order: 4 + +--- + +### What are Tools? + +Tools enable AI systems to interact with external services and perform actions. They provide a structured way for agents and workflows to invoke APIs, manipulate data, and integrate with external systems. Tools form the bridge between AI decision-making capabilities and real-world actions. + +### Understanding Tools + +In an AI system, tools are typically implemented as function calls that the AI can use to accomplish specific tasks. For example, a travel booking agent might have tools for: +- Searching flight availability +- Checking hotel rates +- Processing payments +- Sending confirmation emails + +Each tool has a defined interface specifying its inputs, outputs, and expected behavior. This allows the AI system to understand when and how to use each tool appropriately. + +### Common Tool Patterns + +#### API Integration Tools + +The most common type of tools are those that wrap external APIs. These tools handle the complexity of API authentication, request formatting, and response parsing, presenting a clean interface to the AI system. + +#### Model Context Protocol (MCP) +The (Model Context Protocol)[https://modelcontextprotocol.io/introduction] provides a standardized way to define and interact with tools. Think of it as an abstraction on top of APIs designed for LLMs to interact with external resources. MCP defines a consistent interface for: + +- **Tool Discovery**: Systems can dynamically discover available tools +- **Parameter Validation**: Tools specify their input requirements using JSON Schema +- **Error Handling**: Standardized error reporting and recovery +- **State Management**: Tools can maintain state across invocations + + +#### Data Processing Tools +Tools that handle data transformation and analysis are essential for many AI workflows. These might include: + +- CSV parsing and analysis +- Image processing +- Text extraction +- Data validation + diff --git a/src/content/docs/agents/concepts/what-are-agents.mdx b/src/content/docs/agents/concepts/what-are-agents.mdx index 47a8b1617f22f43..ef11717acea62f0 100644 --- a/src/content/docs/agents/concepts/what-are-agents.mdx +++ b/src/content/docs/agents/concepts/what-are-agents.mdx @@ -1,5 +1,5 @@ --- -title: What are Agents? +title: Agents pcx_content_type: concept sidebar: order: 2 @@ -8,7 +8,7 @@ sidebar: import { Render } from "~/components"; -### What is an agent? +### What are agents? An agent is an AI system that can autonomously execute tasks by making decisions about tool usage and process flow. Unlike traditional automation that follows predefined paths, agents can dynamically adapt their approach based on context and intermediate results. Agents are also distinct from co-pilots (e.g. traditional chat applications) in that they can fully automate a task, as opposed to simply augmenting and extending human input. - **Agents** → non-linear, non-deterministic (can change from run to run) diff --git a/src/content/docs/agents/concepts/workflows.mdx b/src/content/docs/agents/concepts/workflows.mdx index 2c2029eda5d36dc..a36c3f33ab37848 100644 --- a/src/content/docs/agents/concepts/workflows.mdx +++ b/src/content/docs/agents/concepts/workflows.mdx @@ -8,7 +8,24 @@ sidebar: import { Render } from "~/components"; -TODO - what are agents? +### What are workflows? +A workflow is the orchestration layer that coordinates how an agent's components work together. It defines the structured paths through which tasks are processed, tools are called, and results are managed. While agents make dynamic decisions about what to do, workflows provide the underlying framework that governs how those decisions are executed. + +#### Understanding Workflows in Agent Systems + +Think of a workflow like the operating procedures of a company. The company (agent) can make various decisions, but how those decisions get implemented follows established processes (workflows). For example, when you book a flight through a travel agent, they might make different decisions about which flights to recommend, but the process of actually booking the flight follows a fixed sequence of steps. + +Let's examine a basic agent workflow: + +#### Core Components of a Workflow +A workflow typically consists of several key elements: + +1. **Input Processing** +The workflow defines how inputs are received and validated before being processed by the agent. This includes standardizing formats, checking permissions, and ensuring all required information is present. +2. **Tool Integration** +Workflows manage how external tools and services are accessed. They handle authentication, rate limiting, error recovery, and ensuring tools are used in the correct sequence. +3. **State Management** +The workflow maintains the state of ongoing processes, tracking progress through multiple steps and ensuring consistency across operations. +4. **Output Handling** +Results from the agent's actions are processed according to defined rules, whether that means storing data, triggering notifications, or formatting responses. -- terminology -- diagram: orchestrator / container / task / workflow From 7416e63f91487b5a50caa273be08bea8d3db7254 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sun, 23 Feb 2025 16:01:48 -0500 Subject: [PATCH 05/41] limits, schedules --- .../agents/api-reference/configuration.mdx | 71 +++++++++++++++---- src/content/docs/agents/api-reference/sdk.mdx | 26 +------ .../docs/agents/examples/schedule-tasks.mdx | 27 ++++--- src/content/docs/agents/reference/limits.mdx | 31 ++++++++ 4 files changed, 109 insertions(+), 46 deletions(-) create mode 100644 src/content/docs/agents/reference/limits.mdx diff --git a/src/content/docs/agents/api-reference/configuration.mdx b/src/content/docs/agents/api-reference/configuration.mdx index 115d4a401cd62a5..f952f941873d9be 100644 --- a/src/content/docs/agents/api-reference/configuration.mdx +++ b/src/content/docs/agents/api-reference/configuration.mdx @@ -1,28 +1,69 @@ --- -title: Agents SDK +title: pcx_content_type: concept sidebar: - order: 2 + order: 3 --- import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; -This guide details the Agents API within Cloudflare Workers, including methods, types, and usage examples. +An Agent is configured like any other Cloudflare Workers project, and uses [a wrangler configuration](/workers/wrangler/configuration/) file to define where your code is and what services (bindings) it will use. -## Agent +The typical file structure for an Agent project created from `npm create cloudflare@latest -- --template cloudflare/agents` follows: -TODO +```sh +. +|-- package-lock.json +|-- package.json +|-- public +| `-- index.html +|-- src +| `-- index.ts // your Agent definition +|-- test +| |-- index.spec.ts // your tests +| `-- tsconfig.json +|-- tsconfig.json +|-- vitest.config.mts +|-- worker-configuration.d.ts +`-- wrangler.jsonc // your Workers & Agent configuration +``` -The `Agent` class is the core element of a Agent definition: +Below is a minimal `wrangler.jsonc` file that defines the configuration for an Agent, including the entry point, `durable_object` namespace, and code `migrations`: -```ts -import { Agent } from "@cloudflare/agents"; + -export class MyAgent extends Agent { - // methods here - async onRequest(req: Request) { - - } -}; -``` \ No newline at end of file +```jsonc +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "agents-example", + "main": "src/index.ts", + "compatibility_date": "2025-02-23", + "compatibility_flags": ["nodejs_compat"], + "durable_objects": { + "bindings": [ + { + "name": "MyAgent", + "class_name": "MyAgent", + }, + ], + }, + "migrations": [ + { + "tag": "v1", + "new_sqlite_classes": ["MyAgent"], // Mandatory + }, + ], + "observability": { + "enabled": true, + }, +} +``` + + + +The configuration includes: + +- A `main` field that points to the entry point of your Agent, which is typically a TypeScript (or JavaScript) file. +- A `durable_objects` field that defines the [Durable Object namespace](/durable-objects/reference/glossary/) that your Agents will run within. +- A `migrations` field that defines the code migrations that your Agent will use. This field is mandatory and must contain at least one migration. diff --git a/src/content/docs/agents/api-reference/sdk.mdx b/src/content/docs/agents/api-reference/sdk.mdx index 6d63f89936c781a..9e310e7f40c593d 100644 --- a/src/content/docs/agents/api-reference/sdk.mdx +++ b/src/content/docs/agents/api-reference/sdk.mdx @@ -1,31 +1,11 @@ --- -title: Configuration +title: Agents SDK pcx_content_type: concept sidebar: - order: 3 + order: 2 --- import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; -TODO - how to configure an Agent - - - -```json -{ - "name": "my-agent", - "script": "src/index.ts", - // @cloudflare/agents uses Durable Objects - "durable_objects": { - "bindings": [ - { - "binding": "MyAgent", - "class_name": "MyAgent" - } - ] - } -} -``` - - \ No newline at end of file +Each Agent is a JavaScript class that extends the `Agent` class from the `@cloudflare/workers-agents` package. Agents are designed to run in a separate thread from the main Worker, allowing them to perform long-running tasks without blocking the main thread. diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index 0dd47e9a7d8b3c9..ef786014cdab97b 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -3,28 +3,29 @@ title: Schedule tasks pcx_content_type: concept sidebar: order: 5 - --- import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -An Agent can schedule tasks to be run in the future by calling `this.schedule(when, callback, data)`, where `when` can be a delay, a `Date`, or a cron string; callback the function name to call, and data is an object of data to pass to the function. +An Agent can schedule tasks to be run in the future by calling `this.schedule(when, callback, data)`, where `when` can be a delay, a `Date`, or a cron string; `callback` the function name to call, and `data` is an object of data to pass to the function. + +Scheduled tasks can do anything a request or message from a user can: make requests, query databases, send emails, read+write state, etc. ### Scheduling tasks -You can call `this.schedule` within any method on an Agent: +You can call `this.schedule` within any method on an Agent, and schedule tens-of-thousands of tasks per individual Agent. ```ts // schedule a task to run in 10 seconds -this.schedule(10, "myTask", { message: "hello" }); +let task = await this.schedule(10, "myTask", { message: "hello" }); // schedule a task to run at a specific date -this.schedule(new Date("2025-01-01"), "myTask", { message: "hello" }); +let task = await this.schedule(new Date("2025-01-01"), "myTask", { message: "hello" }); // schedule a task to run every 10 seconds -this.schedule("*/10 * * * *", "myTask", { message: "hello" }); +let { id } = await this.schedule("*/10 * * * *", "myTask", { message: "hello" }); // schedule a task to run every 10 seconds, but only on Mondays let task = await this.schedule("0 0 * * 1", "myTask", { message: "hello" }); @@ -35,6 +36,13 @@ this.cancelSchedule(task.id); +Calling `await this.schedule` returns a `Schedule`, which includes the task's randomly generated `id`. You can use this `id` to retrieve or cancel the task in the future. + +:::note[Maximum scheduled tasks] + +Each task is mapped to a row in the Agent's underlying [SQLite database](/sqlite-in-durable-objects/), which means that each task can be up to 2MB in size. The maximum number of tasks must be `(task_size * tasks) + all_other_state < maximum_database_size` (currently 1GB per Agent). + +::: ### Managing scheduled tasks @@ -44,17 +52,20 @@ You can get, cancel and filter across scheduled tasks within an Agent using the ```ts // Get a specific schedule by ID +// Returns undefined if the task does not exist let task = await this.getSchedule(task.id) // Get all scheduled tasks -let tasks = await this.getScheduledTasks(); +// Returns an array of Schedule objects +let tasks = this.getSchedules(); // Cancel a task by its ID +// Returns true if the task was cancelled, false if it did not exist await this.cancelSchedule(task.id); // Filter for specific tasks // e.g. all tasks starting in the next hour -let tasks = this.getSchedules({ // returns an iterator +let tasks = this.getSchedules({ timeRange: { start: new Date(Date.now()), end: new Date(Date.now() + 60 * 60 * 1000), diff --git a/src/content/docs/agents/reference/limits.mdx b/src/content/docs/agents/reference/limits.mdx new file mode 100644 index 000000000000000..3ae7cad80876da8 --- /dev/null +++ b/src/content/docs/agents/reference/limits.mdx @@ -0,0 +1,31 @@ +--- +pcx_content_type: concept +title: Limits +sidebar: + order: 4 + +--- + +import { Render } from "~/components" + +Limits that apply to authoring, deploying, and running Agents are detailed below. + +Many limits are inherited from those applied to Workers scripts and/or Durable Objects, and are detailed in the [Workers limits](/workers/platform/limits/) documentation. + +::: note + +| Feature | Limit | +| ----------------------------------------- | ----------------------- | +| Max concurrent (running) Agents per account | Tens of millions+ [^1] +| Max definitions per account | ~250,000+ [^2] +| Max state stored per unique Agent | 1GB | +| Max compute time per Agent | 30 seconds (refreshed per HTTP request / incoming WebSocket message) [^3] | +| Duration (wall clock) per step [^3] | Unlimited (e.g. waiting on a database call or an LLM response) | + +--- + +[^1]: Yes, really. You can have tens of millions of Agents running concurrently, as each Agent is mapped to a [unique Durable Object](/durable-objects/what-are-durable-objects/) (actor). +[^2]: You can deploy up to [500 scripts per account](/workers/platform/limits/), but each script (project) can define multiple Agents. Each deployed script can be up to 10MB on the [Workers Paid Plan](/workers/platform/pricing/#workers) +[^3]: Compute (CPU) time per Agent is limited to 30 seconds, but this is refreshed when an Agent receives a new HTTP request, runs a [scheduled task](/agents/examples/schedule-tasks/), or an incoming WebSocket message. + + From 4b6b37276e837783264f6b80783b6575c0617150 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sun, 23 Feb 2025 16:34:15 -0500 Subject: [PATCH 06/41] fix config title --- .../agents/api-reference/configuration.mdx | 3 +- .../docs/agents/examples/browse-the-web.mdx | 67 ++++++++++++++++++- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/content/docs/agents/api-reference/configuration.mdx b/src/content/docs/agents/api-reference/configuration.mdx index f952f941873d9be..901041ba97577d9 100644 --- a/src/content/docs/agents/api-reference/configuration.mdx +++ b/src/content/docs/agents/api-reference/configuration.mdx @@ -1,9 +1,8 @@ --- -title: +title: Configuration pcx_content_type: concept sidebar: order: 3 - --- import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/examples/browse-the-web.mdx index 3a924bc93d3b4a2..822f13aaf7de134 100644 --- a/src/content/docs/agents/examples/browse-the-web.mdx +++ b/src/content/docs/agents/examples/browse-the-web.mdx @@ -7,4 +7,69 @@ sidebar: import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -TODO +Agents can browse the web using the [Browser Rendering](/browser-rendering/) API or your preferred headless browser service. + +### Browser Rendering API + +The [Browser Rendering](/browser-rendering/) allows you to spin up headless browser instances, render web pages, and interact with websites through your Agent. + + + +```ts + + +``` + + + +You'll also need to add install the `@cloudflare/puppeteer` package and add the following to the wrangler configuration of your Agent: + +```sh +npm install @cloudflare/puppeteer --save-dev +``` + + + +```jsonc title= +"browser": { + "binding": "MYBROWSER" + }, +``` + + + +### Browserbase + +You can also use [Browserbase](https://docs.browserbase.com/integrations/cloudflare/typescript) by using the Browserbase API directly from within your Agent. + +Once you have your [Browserbase API key](https://docs.browserbase.com/integrations/cloudflare/typescript), you can add it to your Agent by creating a [secret](/workers/configuration/secrets/): + +```sh +cd your-agent-project-folder +npx wrangler@latest secret put BROWSERBASE_API_KEY +``` +```sh output +Enter a secret value: ‚Ķ ****** +Creating the secret for the Worker "agents-example" +Success! Uploaded secret BROWSERBASE_API_KEY +``` + +Install the `@cloudflare/puppeteer` package and use it from within your Agent to call the Browserbase API: + +```sh +npm install @cloudflare/puppeteer +``` + + + +```ts +interface Env { + BROWSERBASE_API_KEY: string; +} + +export class MyAgent extends Agent { + +} +``` + + \ No newline at end of file From 220e6c01246a7d3d54f0489ffed25b4ea03d7750 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sun, 23 Feb 2025 16:42:40 -0500 Subject: [PATCH 07/41] fix --- src/content/docs/agents/api-reference/configuration.mdx | 9 +++++---- src/content/docs/agents/examples/browse-the-web.mdx | 7 ++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/content/docs/agents/api-reference/configuration.mdx b/src/content/docs/agents/api-reference/configuration.mdx index 901041ba97577d9..a6f2dd195ed46ce 100644 --- a/src/content/docs/agents/api-reference/configuration.mdx +++ b/src/content/docs/agents/api-reference/configuration.mdx @@ -42,15 +42,16 @@ Below is a minimal `wrangler.jsonc` file that defines the configuration for an A "durable_objects": { "bindings": [ { - "name": "MyAgent", - "class_name": "MyAgent", + "name": "MyAgent", // How your Agent is called from your Worker + "class_name": "MyAgent", // Must match the class name of the Agent in your code }, ], }, "migrations": [ { "tag": "v1", - "new_sqlite_classes": ["MyAgent"], // Mandatory + // Mandatory for the Agent to store state + "new_sqlite_classes": ["MyAgent"], }, ], "observability": { @@ -65,4 +66,4 @@ The configuration includes: - A `main` field that points to the entry point of your Agent, which is typically a TypeScript (or JavaScript) file. - A `durable_objects` field that defines the [Durable Object namespace](/durable-objects/reference/glossary/) that your Agents will run within. -- A `migrations` field that defines the code migrations that your Agent will use. This field is mandatory and must contain at least one migration. +- A `migrations` field that defines the code migrations that your Agent will use. This field is mandatory and must contain at least one migration. The `new_sqlite_classes` field is mandatory for the Agent to store state. diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/examples/browse-the-web.mdx index 822f13aaf7de134..616cf9a43060dd5 100644 --- a/src/content/docs/agents/examples/browse-the-web.mdx +++ b/src/content/docs/agents/examples/browse-the-web.mdx @@ -16,8 +16,13 @@ The [Browser Rendering](/browser-rendering/) allows you to spin up headless brow ```ts +interface Env { + BROWSER: Fetcher; +} +export class MyAgent extends Agent { +} ``` @@ -72,4 +77,4 @@ export class MyAgent extends Agent { } ``` - \ No newline at end of file + From 32be3ca281bd1f774401b761cae71007e76b57b7 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sun, 23 Feb 2025 17:04:39 -0500 Subject: [PATCH 08/41] fix config --- .../agents/api-reference/configuration.mdx | 3 + .../docs/agents/concepts/workflows.mdx | 10 +-- .../docs/agents/examples/browse-the-web.mdx | 10 ++- .../docs/agents/examples/run-workflows.mdx | 78 +++++++++++++++++++ 4 files changed, 93 insertions(+), 8 deletions(-) diff --git a/src/content/docs/agents/api-reference/configuration.mdx b/src/content/docs/agents/api-reference/configuration.mdx index a6f2dd195ed46ce..7d6df554786b9a6 100644 --- a/src/content/docs/agents/api-reference/configuration.mdx +++ b/src/content/docs/agents/api-reference/configuration.mdx @@ -42,8 +42,11 @@ Below is a minimal `wrangler.jsonc` file that defines the configuration for an A "durable_objects": { "bindings": [ { + // Required: "name": "MyAgent", // How your Agent is called from your Worker "class_name": "MyAgent", // Must match the class name of the Agent in your code + // Optional: set this if the Agent is defined in another Worker script + "script_name": "the-other-worker" }, ], }, diff --git a/src/content/docs/agents/concepts/workflows.mdx b/src/content/docs/agents/concepts/workflows.mdx index a36c3f33ab37848..dd480732120a3ba 100644 --- a/src/content/docs/agents/concepts/workflows.mdx +++ b/src/content/docs/agents/concepts/workflows.mdx @@ -3,21 +3,22 @@ title: Workflows pcx_content_type: concept sidebar: order: 3 - --- import { Render } from "~/components"; -### What are workflows? +## What are workflows? + A workflow is the orchestration layer that coordinates how an agent's components work together. It defines the structured paths through which tasks are processed, tools are called, and results are managed. While agents make dynamic decisions about what to do, workflows provide the underlying framework that governs how those decisions are executed. -#### Understanding Workflows in Agent Systems +### Understanding Workflows in Agent Systems Think of a workflow like the operating procedures of a company. The company (agent) can make various decisions, but how those decisions get implemented follows established processes (workflows). For example, when you book a flight through a travel agent, they might make different decisions about which flights to recommend, but the process of actually booking the flight follows a fixed sequence of steps. Let's examine a basic agent workflow: -#### Core Components of a Workflow +### Core Components of a Workflow + A workflow typically consists of several key elements: 1. **Input Processing** @@ -28,4 +29,3 @@ Workflows manage how external tools and services are accessed. They handle authe The workflow maintains the state of ongoing processes, tracking progress through multiple steps and ensuring consistency across operations. 4. **Output Handling** Results from the agent's actions are processed according to defined rules, whether that means storing data, triggering notifications, or formatting responses. - diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/examples/browse-the-web.mdx index 616cf9a43060dd5..9e177ecb68c3d2a 100644 --- a/src/content/docs/agents/examples/browse-the-web.mdx +++ b/src/content/docs/agents/examples/browse-the-web.mdx @@ -21,7 +21,9 @@ interface Env { } export class MyAgent extends Agent { - + constructor(env: Env) { + super(env); + } } ``` @@ -35,7 +37,7 @@ npm install @cloudflare/puppeteer --save-dev -```jsonc title= +```jsonc "browser": { "binding": "MYBROWSER" }, @@ -73,7 +75,9 @@ interface Env { } export class MyAgent extends Agent { - + constructor(env: Env) { + super(env); + } } ``` diff --git a/src/content/docs/agents/examples/run-workflows.mdx b/src/content/docs/agents/examples/run-workflows.mdx index b2c86d98a3a9d7f..4cc72f7482e6aef 100644 --- a/src/content/docs/agents/examples/run-workflows.mdx +++ b/src/content/docs/agents/examples/run-workflows.mdx @@ -9,3 +9,81 @@ sidebar: import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; TODO - show how to invoke a Workflow from an Agent + +Agents can trigger asynchronous [Workflows](/workflows/), allowing your Agent to run complex, multi-step tasks in the background. This can include post-processing files that a user has uploaded, updating the embeddings in a [vector database](/vectorize/), and/or managing long-running user-lifecycle email or SMS notification workflows. + +Because an Agent is just like a Worker script, it can create Workflows defined in the same project (script) as the Agent _or_ in a different project. + +## Trigger a Workflow + + + +```ts +interface Env { + BROWSER: Fetcher; +} + +export class MyAgent extends Agent { + +} +``` + + + + + +```jsonc +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "agents-example", + "main": "src/index.ts", + "compatibility_date": "2025-02-23", + "compatibility_flags": ["nodejs_compat"], + // Create a binding between your Agent and your Workflow + "workflows": [{ "name": "EMAIL_WORKFLOW", "class_name": "EmailWorkflow" }], + "durable_objects": { + "bindings": [ + { + "name": "MyAgent", + "class_name": "MyAgent", + }, + ], + }, + "migrations": [ + { + "tag": "v1", + // Mandatory for the Agent to store state + "new_sqlite_classes": ["MyAgent"], + }, + ], + "observability": { + "enabled": true, + }, +} +``` + + + +## Trigger a Workflow from another project + +You can also call a Workflow that is defined in a different Workers script from your Agent by setting the `script_name` property in the `workflows` binding of your Agent: + + + +```jsonc +{ + // ... + "workflows": [ + { "name": "EMAIL_WORKFLOW", + "class_name": "EmailWorkflow", + // Set script_name to the name of the Worker that contains the EmailWorkflow definition + "script_name": "email-workflow-prod" + }, + ], + // ... +} +``` + + + +Refer to the [cross-script calls](/workflows/build/workers-api/#cross-script-calls) section of the Workflows documentation for more examples. From 60d0f2f29a01103d5894ad24e11ab8b139d67416 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sun, 23 Feb 2025 20:47:54 -0500 Subject: [PATCH 09/41] websockets --- .../docs/agents/examples/browse-the-web.mdx | 8 +- .../docs/agents/examples/schedule-tasks.mdx | 34 ++++- .../docs/agents/examples/websockets.mdx | 141 +++++++++++++++++- 3 files changed, 174 insertions(+), 9 deletions(-) diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/examples/browse-the-web.mdx index 9e177ecb68c3d2a..a95cad4e3abb7cb 100644 --- a/src/content/docs/agents/examples/browse-the-web.mdx +++ b/src/content/docs/agents/examples/browse-the-web.mdx @@ -38,9 +38,13 @@ npm install @cloudflare/puppeteer --save-dev ```jsonc -"browser": { +{ + // ... + "browser": { "binding": "MYBROWSER" - }, + } + // ... +} ``` diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index ef786014cdab97b..08fba37faef456a 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -9,26 +9,48 @@ import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/com An Agent can schedule tasks to be run in the future by calling `this.schedule(when, callback, data)`, where `when` can be a delay, a `Date`, or a cron string; `callback` the function name to call, and `data` is an object of data to pass to the function. -Scheduled tasks can do anything a request or message from a user can: make requests, query databases, send emails, read+write state, etc. +Scheduled tasks can do anything a request or message from a user can: make requests, query databases, send emails, read+write state: scheduled tasks can invoke any regular method on your Agent. ### Scheduling tasks -You can call `this.schedule` within any method on an Agent, and schedule tens-of-thousands of tasks per individual Agent. +You can call `this.schedule` within any method on an Agent, and schedule tens-of-thousands of tasks per individual Agent: + +```ts +import { Agent } from "@cloudflare/agents" + +export class SchedulingAgent extends Agent { + async onRequest(request) { + // Handle an incoming request + // Schedule a task 5 minutes from now + // Calls the "checkFlights" method + let { taskId } = await this.schedule(600, "checkFlights", { flight: "DL264", date: "2025-02-23" }); + return Response.json({ taskId }); + } + + async checkFlights(data) { + // Invoked when our scheduled task runs + // We can also call this.schedule here to schedule another task + } +} +``` + + +You can schedule tasks in multiple ways: ```ts // schedule a task to run in 10 seconds -let task = await this.schedule(10, "myTask", { message: "hello" }); +let task = await this.schedule(10, "someTask", { message: "hello" }); // schedule a task to run at a specific date -let task = await this.schedule(new Date("2025-01-01"), "myTask", { message: "hello" }); +let task = await this.schedule(new Date("2025-01-01"), "someTask", {}); // schedule a task to run every 10 seconds -let { id } = await this.schedule("*/10 * * * *", "myTask", { message: "hello" }); +let { id } = await this.schedule("*/10 * * * *", "someTask", { message: "hello" }); // schedule a task to run every 10 seconds, but only on Mondays -let task = await this.schedule("0 0 * * 1", "myTask", { message: "hello" }); +let task = await this.schedule("0 0 * * 1", "someTask", { message: "hello" }); // cancel a scheduled task this.cancelSchedule(task.id); diff --git a/src/content/docs/agents/examples/websockets.mdx b/src/content/docs/agents/examples/websockets.mdx index 40114ee5c4e87e4..d113e8d117cf8c4 100644 --- a/src/content/docs/agents/examples/websockets.mdx +++ b/src/content/docs/agents/examples/websockets.mdx @@ -8,4 +8,143 @@ sidebar: import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -TODO +Users and clients can connect to an Agent directly over WebSockets, allowing long-running, bi-directional communication with your Agent as it operates. + +To enable an Agent to accept WebSockets, define `onConnect` and `onMessage` methods on your Agent. + +* `onConnect(connection: Connection, ctx: ConnectionContext)` is called when a client establishes a new WebSocket connection. The original HTTP request, including request headers, cookies and the URL itself, are available on `ctx.request`. +* `onMessage(connection: Connection, message: WSMessage)` is called for each incoming WebSocket message. Messages are one of `ArrayBuffer | ArrayBufferView | string`, and you can send messages back to a client using `connection.send()`. You can distinguish between client connections by checking `connection.id`, which is unique for each connected client. + +Here's an example of an Agent that echoes back any message it receives: + + + +```ts +import { Agent, Connection } from "@cloudflare/agents"; + +export class ChatAgent extends Agent { + async onConnect(connection: Connection, ctx: ConnectionContext) { + // Access the request to verify any authentication tokens + // provided in headers or cookies + let token = ctx.request.headers.get("Authorization"); + if (!token) { + await connection.close(4000, "Unauthorized"); + return; + } + + // Handle auth using your favorite library and/or auth scheme: + // try { + // await jwt.verify(token, env.JWT_SECRET); + // } catch (error) { + // connection.close(4000, 'Invalid Authorization header'); + // return; + // } + + // Accept valid connections + connection.accept() + } + + async onMessage(connection: Connection, message: WSMessage) { + // const response = await longRunningAITask(message) + await connection.send(message) + } +} +``` + + + +## Connecting clients + +The Agent framework includes a useful helper package for connecting directly to your agent (or other agents) from a client application. Import `@cloudflare/agents/client`, create an instance of `AgentClient` and use it to connect to an instance of your Agent: + + + +```ts +import { AgentClient } from "@cloudflare/agents/client"; + +const connection = new AgentClient({ + agent: "dialogue-agent", + name: "insight-seeker", +}); + +connection.addEventListener("message", (event) => { + console.log("Received:", event.data); +}); + +connection.send( + JSON.stringify({ + type: "inquiry", + content: "What patterns do you see?", + }) +); +``` + + + +## React clients + +React-based applications can import `@cloudflare/agents/react` and use the `useAgent` hook to connect to an instance of an Agent directly: + + + +```ts +import { useAgent } from "@cloudflare/agents/react"; + +function AgentInterface() { + const connection = useAgent({ + agent: "dialogue-agent", + name: "insight-seeker", + onMessage: (message) => { + console.log("Understanding received:", message.data); + }, + onOpen: () => console.log("Connection established"), + onClose: () => console.log("Connection closed"), + }); + + const inquire = () => { + connection.send( + JSON.stringify({ + type: "inquiry", + content: "What insights have you gathered?", + }) + ); + }; + + return ( +
+ +
+ ); +} + +``` + + +The `useAgent` hook automatically handles the lifecycle of the connection, ensuring that it is properly initialized and cleaned up when the component mounts and unmounts. You can also [combine `useAgent` with `useState`](/agents/examples/manage-and-sync-state/) to automatically synchronize state across all clients connected to your agent. + +## Handling WebSocket events + +Define `onError` and `onClose` methods on your Agent to explicitly handle WebSocket client errors and close events. Log errors, clean up state, and/or emit metrics: + + + +```ts +import { Agent, Connection } from "@cloudflare/agents"; + +export class ChatAgent extends Agent { + // onConnect and onMessage methods + // ... + + // WebSocket error and disconnection (close) handling. + async onError(connection: Connection, error: unknown): Promise { + console.error(`WS error: ${error}`); + } + async onClose(connection: Connection, code: number, reason: string, wasClean: boolean): Promise { + console.log(`WS closed: ${code} - ${reason} - wasClean: ${wasClean}`); + connection.close(); + } +} + +``` + + From 96350104fa56122cbfda7fcf20e3dca0faf81b1f Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sun, 23 Feb 2025 21:00:38 -0500 Subject: [PATCH 10/41] fix closing tag --- src/content/docs/agents/api-reference/sdk.mdx | 25 ++++++++++++++++++- .../docs/agents/examples/schedule-tasks.mdx | 4 +++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/content/docs/agents/api-reference/sdk.mdx b/src/content/docs/agents/api-reference/sdk.mdx index 9e310e7f40c593d..eeeada02e102e4a 100644 --- a/src/content/docs/agents/api-reference/sdk.mdx +++ b/src/content/docs/agents/api-reference/sdk.mdx @@ -8,4 +8,27 @@ sidebar: import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; -Each Agent is a JavaScript class that extends the `Agent` class from the `@cloudflare/workers-agents` package. Agents are designed to run in a separate thread from the main Worker, allowing them to perform long-running tasks without blocking the main thread. +At its most basic, an Agent is a JavaScript class that extends the `Agent` class from the `@cloudflare/agents` package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. + + + +```ts +import { Agent } from "@cloudflare/agents"; + +class MyAgent extends Agent { + // Define methods on the Agent +} + +export default MyAgent; +``` + + + +An Agent can have many (millions of) instances: each instance is a separate micro-server that runs independently of the others. This allows Agents to scale horizontally: an Agent can be associated with a single user, or many thousands of users, depending on the agent you're building. + +Instances of an Agent are addressed by a unique identifier: that identifier (ID) can be the user ID, an email address, GitHub username, a flight ticket number, an invoice ID, or any other identifier that helps to uniquely identify the instance and for whom it is acting on behalf of. + +## Agent + +TODO - agent class + diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index 08fba37faef456a..8c82972d5052f87 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -15,6 +15,8 @@ Scheduled tasks can do anything a request or message from a user can: make reque You can call `this.schedule` within any method on an Agent, and schedule tens-of-thousands of tasks per individual Agent: + + ```ts import { Agent } from "@cloudflare/agents" @@ -60,6 +62,8 @@ this.cancelSchedule(task.id); Calling `await this.schedule` returns a `Schedule`, which includes the task's randomly generated `id`. You can use this `id` to retrieve or cancel the task in the future. +Tasks that set a callback for a method that does not exist will fail silently. + :::note[Maximum scheduled tasks] Each task is mapped to a row in the Agent's underlying [SQLite database](/sqlite-in-durable-objects/), which means that each task can be up to 2MB in size. The maximum number of tasks must be `(task_size * tasks) + all_other_state < maximum_database_size` (currently 1GB per Agent). From b67a3c643f6a97b2ffb4c232e66066e483a65b23 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Sun, 23 Feb 2025 21:07:16 -0500 Subject: [PATCH 11/41] caution --- src/content/docs/agents/examples/schedule-tasks.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index 8c82972d5052f87..8614e3f96dff631 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -60,10 +60,14 @@ this.cancelSchedule(task.id); -Calling `await this.schedule` returns a `Schedule`, which includes the task's randomly generated `id`. You can use this `id` to retrieve or cancel the task in the future. +:::caution Tasks that set a callback for a method that does not exist will fail silently. +::: + +Calling `await this.schedule` returns a `Schedule`, which includes the task's randomly generated `id`. You can use this `id` to retrieve or cancel the task in the future. It also provides a `type` property that indicates the type of schedule - e.g. one of `"scheduled" | "delayed" | "cron"`. + :::note[Maximum scheduled tasks] Each task is mapped to a row in the Agent's underlying [SQLite database](/sqlite-in-durable-objects/), which means that each task can be up to 2MB in size. The maximum number of tasks must be `(task_size * tasks) + all_other_state < maximum_database_size` (currently 1GB per Agent). From 336327228d6b8fc1f44580bf74a81e1e7d09e240 Mon Sep 17 00:00:00 2001 From: Jun Lee Date: Mon, 24 Feb 2025 14:13:06 +0000 Subject: [PATCH 12/41] Apply suggestions from code review --- src/content/docs/agents/api-reference/configuration.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/agents/api-reference/configuration.mdx b/src/content/docs/agents/api-reference/configuration.mdx index 7d6df554786b9a6..24563dce3c49ce7 100644 --- a/src/content/docs/agents/api-reference/configuration.mdx +++ b/src/content/docs/agents/api-reference/configuration.mdx @@ -28,7 +28,7 @@ The typical file structure for an Agent project created from `npm create cloudfl `-- wrangler.jsonc // your Workers & Agent configuration ``` -Below is a minimal `wrangler.jsonc` file that defines the configuration for an Agent, including the entry point, `durable_object` namespace, and code `migrations`: +Below is a minimal `wrangler.jsonc` file that defines the configuration for an Agent, including the entry point, `durable_object` namespace, and code `migrations`: From c43f550b025fb1eacb444c489bbd66a585115369 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 10:12:51 -0500 Subject: [PATCH 13/41] state state state --- src/content/docs/agents/api-reference/sdk.mdx | 134 +++++++++++++++++- src/content/docs/agents/examples/index.mdx | 6 +- .../agents/examples/manage-and-sync-state.mdx | 57 +++++++- 3 files changed, 187 insertions(+), 10 deletions(-) diff --git a/src/content/docs/agents/api-reference/sdk.mdx b/src/content/docs/agents/api-reference/sdk.mdx index eeeada02e102e4a..8be66c7c0e88781 100644 --- a/src/content/docs/agents/api-reference/sdk.mdx +++ b/src/content/docs/agents/api-reference/sdk.mdx @@ -6,7 +6,7 @@ sidebar: --- -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; +import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; At its most basic, an Agent is a JavaScript class that extends the `Agent` class from the `@cloudflare/agents` package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. @@ -28,7 +28,135 @@ An Agent can have many (millions of) instances: each instance is a separate micr Instances of an Agent are addressed by a unique identifier: that identifier (ID) can be the user ID, an email address, GitHub username, a flight ticket number, an invoice ID, or any other identifier that helps to uniquely identify the instance and for whom it is acting on behalf of. -## Agent +## The Agent class -TODO - agent class +Writing an Agent requires you to define a class that extends the `Agent` class from the `@cloudflare/agents` package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. +An Agent has the following class methods: + + + +```ts +import { Agent } from "@cloudflare/agents"; + +interface Env { + // Define environment variables & bindings here +} + +// Pass the Env as a TypeScript type argument +// Any services connected to your Agent or Worker as Bindings +// are then available on this.env. +class MyAgent extends Agent { + // Called when an Agent is started (or woken up) + async onStart() { + // Can access this.env and this.state + console.log('Agent started'); + } + + // Called when a HTTP request is received + // Can be connected to routeAgentRequest to automatically route + // requests to an individual Agent. + async onRequest(request: Request) { + console.log("Received request!"); + } + + // Called when a WebSocket connection is established + async onConnect(connection: Connection, ctx: ConnectionContext) { + console.log("Connected!"); + // Check the request at ctx.request + // Authenticate the client + // Give them the OK. + connection.accept(); + } + + // Called for each message received on the WebSocket connection + async onMessage(connection: Connection, message: WSMessage) { + console.log(`message from client ID: ${connection.id}`) + // Send messages back to the client + connection.send("Hello!"); + } + + // WebSocket error and disconnection (close) handling. + async onError(connection: Connection, error: unknown): Promise { + console.error(`WS error: ${error}`); + } + + async onClose(connection: Connection, code: number, reason: string, wasClean: boolean): Promise { + console.log(`WS closed: ${code} - ${reason} - wasClean: ${wasClean}`); + connection.close(); + } + + // Called when the Agent's state is updated + // via this.setState or the useAgent hook from the @cloudflare/agents/react package. + async onStateUpdate(state: any) { + // 'state' will be typed if you supply a type parameter to the Agent class. + } +} + +export default MyAgent; +``` + + + +:::note + +To learn more about how to manage state within an Agent, refer to the documentation on [managing and syncing state](/agents/examples/manage-and-sync-state/). + +::: + +You can also define your own methods on an Agent: it's technically valid to publish an Agent only has your own methods exposed, and create/get Agents directly from a Worker. + +Your own methods can access the Agent's environment variables and bindings on `this.env`, state on `this.setState`, and call other methods on the Agent via `this.yourMethodName`. + +## Calling Agents from Workers + +You can create and run an instance of an Agent directly from a Worker in one of three ways: + +1. Using the `routeAgentRequest` helper: this will automatically map requests to an individual Agent based on the `/agents/:agent/:name` URL pattern. +2. Calling `getAgentByName`, which will create a new Agent instance if none exists by that name, or retrieve a handle to an existing instance. +3. The [Durable Objects stub API](/durable-objects/api/id/), which provides a lower level API for creating and retrieving Agents. + +These three patterns are shown below: we recommend using either `routeAgentRequest` or `getAgentByName`, which help avoid some boilerplate. + + + +```ts +import { Agent, AgentNamespace, getAgentByName, routeAgentRequest } from '@cloudflare/agents'; + +interface Env { + // Define your Agent on the environment here + // Passing your Agent class as a TypeScript type parameter allows you to call + // methods defined on your Agent. + MyAgent: AgentNamespace; +} + +export default { + async fetch(request, env, ctx): Promise { + // Routed addressing + // Automatically routes HTTP requests and/or WebSocket connections to /agents/:agent/:name + // Best for: connecting React apps directly to Agents using useAgent from @cloudflare/agents/react + (await routeAgentRequest(request, env)) || Response.json({ msg: 'no agent here' }, { status: 404 }); + + // Named addressing + // Best for: convenience method for creating or retrieving an agent by name/ID. + let namedAgent = getAgentByName(env.MyAgent, 'my-unique-agent-id'); + // Pass the incoming request straight to your Agent + let namedResp = (await namedAgent).fetch(request); + + // Durable Objects-style addressing + // Best for: controlling ID generation, associating IDs with your existing systems, + // and customizing when/how an Agent is created or invoked + const id = env.MyAgent.newUniqueId(); + const agent = env.MyAgent.get(id); + // Pass the incoming request straight to your Agent + let resp = await agent.fetch(request); + + return Response.json({ hello: 'visit https://developers.cloudflare.com/agents for more' }); + }, +} satisfies ExportedHandler; + +export class MyAgent extends Agent { + // Your Agent implementation goes here +} +``` + diff --git a/src/content/docs/agents/examples/index.mdx b/src/content/docs/agents/examples/index.mdx index 97954a89801c9f6..653759643e4a623 100644 --- a/src/content/docs/agents/examples/index.mdx +++ b/src/content/docs/agents/examples/index.mdx @@ -3,12 +3,10 @@ pcx_content_type: reference title: Build sidebar: order: 4 - group: - hideIndex: true --- -import { DirectoryListing } from "~/components"; +import { DirectoryListing, PackageManagers } from "~/components"; -Build AI Agents on Cloudflare +Agents running on Cloudflare can: diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx index 5b04d9ca3efe42e..527fec1026656bd 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -14,9 +14,11 @@ Every Agent has built-in state management capabilities, including built-in stora * Immediately consistent within the Agent: read your own writes. * Thread-safe for concurrent updates -### State management +Agent state is stored in SQL database that associate with each indidivual Agent instance: you can interact with it using the higher-level `this.setState` API (recommended) or by directly querying the database with `this.sql`. -Every agent has built-in state management capabilities. You can set and update the agent's state directly using `this.state`: +### State API + +Every agent has built-in state management capabilities. You can set and update the agent's state directly using `this.setState`: @@ -51,6 +53,32 @@ export class MyAgent extends Agent { +If you're using TypeScript, you can also provide a type for your Agent's state by passing in a type as a [type parameter](https://www.typescriptlang.org/docs/handbook/2/generics.html#using-type-parameters-in-generic-constraints) as the _second_ type parameter to the `Agent` class definition. + + + +```ts +import { Agent } from "@cloudflare/agents"; + +interface Env {} + +// +interface FlightRecord { + id: string; + departureIata: string; + arrival: Date;; + arrivalIata: string; + price: number; +} + +// Pass in the type of your Agent's state +export class MyAgent extends Agent { + // This allows this.setState and +} +``` + + + ### Synchronizing state Clients can connect to an Agent and stay synchronized with its state using the React hooks provided as part of `@cloudflare/agents/react`: @@ -78,4 +106,27 @@ Common use cases: * Multi-window/tab synchronization * Live updates across multiple devices * Maintaining consistent UI state across clients -* When new clients connect, they automatically receive the current state from the agent, ensuring all clients start with the latest data. \ No newline at end of file +* When new clients connect, they automatically receive the current state from the agent, ensuring all clients start with the latest data. + +### SQL API + +Every individual Agent instance has its own SQL (SQLite) database that runs _within the same context_ as the Agent itself. This means that inserting or querying data within your Agent is effectively zero-latency: the Agent doesn't have to round-trip across a continent or the world to access its own data. + +TODO + + + +```ts + + +``` + + + +:::note + +Learn more about the zero-latency SQL storage that powers both Agents and Durable Objects [on our blog](https://blog.cloudflare.com/sqlite-in-durable-objects/). + +::: + +The SQL API exposed to an Agent is identical to the one [within by Durable Objects](/durable-objects/api/sql-storage/). This means that you can use the same SQL queries and commands to interact with the Agent's database. From 7267caf3711566da3fe9e901dd3a742670f1e40b Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 10:51:26 -0500 Subject: [PATCH 14/41] sql API yo yo yo --- .../agents/examples/manage-and-sync-state.mdx | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx index 527fec1026656bd..a8403420c14b196 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -112,16 +112,47 @@ Common use cases: Every individual Agent instance has its own SQL (SQLite) database that runs _within the same context_ as the Agent itself. This means that inserting or querying data within your Agent is effectively zero-latency: the Agent doesn't have to round-trip across a continent or the world to access its own data. -TODO +You can access the SQL API within any method on an Agent via `this.sql`. The SQL API accepts template literals, and ```ts +export class MyAgent extends Agent { + async onRequest(request: Request) { + let userId = new URL(request.url).searchParams.get('userId'); + + // 'users' is just an example here: you can create arbitrary tables and define your own schemas + // within each Agent's database using SQL (SQLite syntax). + let user = await this.sql`SELECT * FROM users WHERE id = ${userId}` + return Response.json(user) + } +} +``` + + +You can also supply a [TypeScript type argument](https://www.typescriptlang.org/docs/handbook/2/generics.html#using-type-parameters-in-generic-constraints) the query, which will be used to infer the type of the result: +```ts +type User = { + id: string; + name: string; + email: string; +}; + +export class MyAgent extends Agent { + async onRequest(request: Request) { + let userId = new URL(request.url).searchParams.get('userId'); + // Supply the type paramter to the query when calling this.sql + // This assumes the results return a single User row with "id", "name", and "email" columns + // You can also pass an array as the type argument to the query - e.g. User[] + const user = await this.sql`SELECT * FROM users WHERE id = ${userId}`; + return Response.json(user) + } +} ``` - +Providing a type parameter does not validate that the result matches your type definition. In TypeScript, properties (fields) that do not exist or conform to the type you provided will be dropped. If you need to validate incoming events, we recommend a library such as [zod](https://zod.dev/) or your own validator logic. :::note @@ -129,4 +160,4 @@ Learn more about the zero-latency SQL storage that powers both Agents and Durabl ::: -The SQL API exposed to an Agent is identical to the one [within by Durable Objects](/durable-objects/api/sql-storage/). This means that you can use the same SQL queries and commands to interact with the Agent's database. +The SQL API exposed to an Agent is similar to the one [within Durable Objects](/durable-objects/api/sql-storage/). This means that you can use the same SQL queries with the Agent's database, create tables, and query data. From f9f6c4ea36d3093732acfb990f039de479261906 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 11:09:13 -0500 Subject: [PATCH 15/41] agents: Apply suggestions from code review Co-authored-by: Jun Lee --- .../docs/agents/concepts/calling-llms.mdx | 7 ++++-- .../agents/concepts/human-in-the-loop.mdx | 21 +++++++++-------- src/content/docs/agents/concepts/tools.mdx | 13 +++++++---- .../docs/agents/concepts/what-are-agents.mdx | 23 ++++++++++++------- .../docs/agents/concepts/workflows.mdx | 4 ++-- .../agents/examples/manage-and-sync-state.mdx | 6 ++--- .../docs/agents/examples/schedule-tasks.mdx | 4 ++-- .../docs/agents/examples/using-ai-models.mdx | 4 ++-- .../docs/agents/examples/websockets.mdx | 6 ++--- src/content/docs/agents/index.mdx | 2 +- .../agents/reference/agents-vs-workflows.mdx | 2 +- src/content/docs/agents/reference/limits.mdx | 4 ++-- 12 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/content/docs/agents/concepts/calling-llms.mdx b/src/content/docs/agents/concepts/calling-llms.mdx index 855f8bef8b410c5..b9956d96b606467 100644 --- a/src/content/docs/agents/concepts/calling-llms.mdx +++ b/src/content/docs/agents/concepts/calling-llms.mdx @@ -8,12 +8,14 @@ sidebar: import { Render } from "~/components"; -### Understanding LLM Providers and Model Types +### Understanding LLM providers and model types Different LLM providers offer models optimized for specific types of tasks. When building AI systems, choosing the right model is crucial for both performance and cost efficiency. #### Reasoning Models + Models like OpenAI's o1, Anthropic's Claude, and DeepSeek's R1 are particularly well-suited for complex reasoning tasks. These models excel at: + - Breaking down problems into steps - Following complex instructions - Maintaining context across long conversations @@ -22,10 +24,11 @@ Models like OpenAI's o1, Anthropic's Claude, and DeepSeek's R1 are particularly For example, when implementing a travel booking system, you might use a reasoning model to analyze travel requirements and generate appropriate booking strategies. #### Instruction Models + Models like GPT-4 and Claude Instant are optimized for following straightforward instructions efficiently. They work well for: - Content generation - Simple classification tasks - Basic question answering - Text transformation -These models are often more cost-effective for straightforward tasks that don't require complex reasoning. \ No newline at end of file +These models are often more cost-effective for straightforward tasks that do not require complex reasoning. \ No newline at end of file diff --git a/src/content/docs/agents/concepts/human-in-the-loop.mdx b/src/content/docs/agents/concepts/human-in-the-loop.mdx index 11e14e496bfe4ef..22917ef538737e8 100644 --- a/src/content/docs/agents/concepts/human-in-the-loop.mdx +++ b/src/content/docs/agents/concepts/human-in-the-loop.mdx @@ -14,29 +14,30 @@ Human-in-the-Loop (HITL) workflows integrate human judgment and oversight into a ![A human-in-the-loop diagram](~/assets/images/agents/human-in-the-loop.svg) -#### Understanding Human-in-the-Loop Workflows +#### Understanding Human-in-the-Loop workflows -In a Human-in-the-Loop workflow, processes aren't fully automated. Instead, they include designated checkpoints where human intervention is required. For example, in a travel booking system, a human may want to confirm the travel before an agent follows through with a transaction. The workflow manages this interaction, ensuring that: +In a Human-in-the-Loop workflow, processes are not fully automated. Instead, they include designated checkpoints where human intervention is required. For example, in a travel booking system, a human may want to confirm the travel before an agent follows through with a transaction. The workflow manages this interaction, ensuring that: 1. The process pauses at appropriate review points 2. Human reviewers receive necessary context 3. The system maintains state during the review period 4. Review decisions are properly incorporated -5. The process continues once approval is receive +5. The process continues once approval is received -### Best Practices for Human-in-the-Loop Workflows +### Best practices for Human-in-the-Loop workflows #### Long-Term State Persistence -Human review processes don't operate on predictable timelines. A reviewer might need days or weeks to make a decision, especially for complex cases requiring additional investigation or multiple approvals. Your system needs to maintain perfect state consistency throughout this period, including: +Human review processes do not operate on predictable timelines. A reviewer might need days or weeks to make a decision, especially for complex cases requiring additional investigation or multiple approvals. Your system needs to maintain perfect state consistency throughout this period, including: + - The original request and context - All intermediate decisions and actions - Any partial progress or temporary states - Review history and feedback - +:::note[Tip] +[Durable Objects](/durable-objects/) provide an ideal solution for managing state in Human-in-the-Loop workflows, offering persistent compute instances that maintain state for hours, weeks, or months. +::: #### Continuous Improvement Through Evals @@ -44,9 +45,9 @@ Human reviewers play a crucial role in evaluating and improving LLM performance. - Decision Quality Assessment: Have reviewers evaluate the LLM's reasoning process and decision points, not just the final output. - Edge Case Identification: Use human expertise to identify scenarios where the LLM's performance could be improved. -- Feedback Collection: Gather structured feedback that can be used to fine-tune the LLM or adjust the workflow. [AI Gateway](https://developers.cloudflare.com/ai-gateway/evaluations/add-human-feedback/) can be a useful tool for setting up an LLM feedback loop. +- Feedback Collection: Gather structured feedback that can be used to fine-tune the LLM or adjust the workflow. [AI Gateway](/ai-gateway/evaluations/add-human-feedback/) can be a useful tool for setting up an LLM feedback loop. -#### Error Handling and Recovery +#### Error handling and recovery Robust error handling is essential for maintaining workflow integrity. Your system should gracefully handle various failure scenarios, including reviewer unavailability, system outages, or conflicting reviews. Implement clear escalation paths for handling exceptional cases that fall outside normal parameters. diff --git a/src/content/docs/agents/concepts/tools.mdx b/src/content/docs/agents/concepts/tools.mdx index 424b123d51b3c59..b5a235895dd50e0 100644 --- a/src/content/docs/agents/concepts/tools.mdx +++ b/src/content/docs/agents/concepts/tools.mdx @@ -6,13 +6,14 @@ sidebar: --- -### What are Tools? +### What are tools? Tools enable AI systems to interact with external services and perform actions. They provide a structured way for agents and workflows to invoke APIs, manipulate data, and integrate with external systems. Tools form the bridge between AI decision-making capabilities and real-world actions. -### Understanding Tools +### Understanding tools In an AI system, tools are typically implemented as function calls that the AI can use to accomplish specific tasks. For example, a travel booking agent might have tools for: + - Searching flight availability - Checking hotel rates - Processing payments @@ -20,13 +21,14 @@ In an AI system, tools are typically implemented as function calls that the AI c Each tool has a defined interface specifying its inputs, outputs, and expected behavior. This allows the AI system to understand when and how to use each tool appropriately. -### Common Tool Patterns +### Common tool patterns -#### API Integration Tools +#### API integration tools The most common type of tools are those that wrap external APIs. These tools handle the complexity of API authentication, request formatting, and response parsing, presenting a clean interface to the AI system. #### Model Context Protocol (MCP) + The (Model Context Protocol)[https://modelcontextprotocol.io/introduction] provides a standardized way to define and interact with tools. Think of it as an abstraction on top of APIs designed for LLMs to interact with external resources. MCP defines a consistent interface for: - **Tool Discovery**: Systems can dynamically discover available tools @@ -35,7 +37,8 @@ The (Model Context Protocol)[https://modelcontextprotocol.io/introduction] provi - **State Management**: Tools can maintain state across invocations -#### Data Processing Tools +#### Data processing tools + Tools that handle data transformation and analysis are essential for many AI workflows. These might include: - CSV parsing and analysis diff --git a/src/content/docs/agents/concepts/what-are-agents.mdx b/src/content/docs/agents/concepts/what-are-agents.mdx index ef11717acea62f0..5bd4d932fe6602e 100644 --- a/src/content/docs/agents/concepts/what-are-agents.mdx +++ b/src/content/docs/agents/concepts/what-are-agents.mdx @@ -8,20 +8,24 @@ sidebar: import { Render } from "~/components"; -### What are agents? +### What are agents? + An agent is an AI system that can autonomously execute tasks by making decisions about tool usage and process flow. Unlike traditional automation that follows predefined paths, agents can dynamically adapt their approach based on context and intermediate results. Agents are also distinct from co-pilots (e.g. traditional chat applications) in that they can fully automate a task, as opposed to simply augmenting and extending human input. - **Agents** → non-linear, non-deterministic (can change from run to run) - **Workflows** → linear, deterministic execution paths - **Co-pilots** → augmentative AI assistance requiring human intervention -### Example: Booking Vacations -If this is your first time working with, or interacting with agents, this example will illustrate how an agent works within a context like booking a vacation. If you're already familiar with the topic, read on. +### Example: Booking vacations + +If this is your first time working with, or interacting with agents, this example will illustrate how an agent works within a context like booking a vacation. If you are already familiar with the topic, read on. Imagine you're trying to book a vacation. You need to research flights, find hotels, check restaurant reviews, and keep track of your budget. -##### Traditional Workflow Automation +#### Traditional workflow automation + A traditional automation system follows a predetermined sequence: + - Takes specific inputs (dates, location, budget) - Calls predefined API endpoints in a fixed order - Returns results based on hardcoded criteria @@ -29,7 +33,8 @@ A traditional automation system follows a predetermined sequence: ![Traditional workflow automation diagram](~/assets/images/agents/workflow-automation.svg) -##### AI Co-pilot +#### AI Co-pilot + A co-pilot acts as an intelligent assistant that: - Provides hotel and itinerary recommendations based on your preferences @@ -39,7 +44,8 @@ A co-pilot acts as an intelligent assistant that: ![A co-pilot diagram](~/assets/images/agents/co-pilot.svg) -##### Agent +#### Agent + An agent combines AI's ability to make judgements and call the relevant tools to execute the task. An agent's output will be nondeterministic given: - Real-time availability and pricing changes @@ -49,7 +55,7 @@ An agent combines AI's ability to make judgements and call the relevant tools to ![An agent diagram](~/assets/images/agents/agent-workflow.svg) -An agents can dynamically generate and itinerary and execute on booking reservations, similarly to what you would expect from a travel agent. +An agents can dynamically generate an itinerary and execute on booking reservations, similarly to what you would expect from a travel agent. ### Three primary components of agent systems: @@ -57,9 +63,10 @@ An agents can dynamically generate and itinerary and execute on booking reservat - **Tool Integration**: APIs, functions, and services the agent can utilize - **Memory System**: Maintains context and tracks task progress -#### How Agents Work +#### How agents work Agents operate in a continuous loop of: + 1. **Observing** the current state or task 2. **Planning** what actions to take, using AI for reasoning 3. **Executing** those actions using available tools (often APIs or [MCPs](https://modelcontextprotocol.io/introduction)) diff --git a/src/content/docs/agents/concepts/workflows.mdx b/src/content/docs/agents/concepts/workflows.mdx index dd480732120a3ba..a0ea8d69aa7e2d2 100644 --- a/src/content/docs/agents/concepts/workflows.mdx +++ b/src/content/docs/agents/concepts/workflows.mdx @@ -11,13 +11,13 @@ import { Render } from "~/components"; A workflow is the orchestration layer that coordinates how an agent's components work together. It defines the structured paths through which tasks are processed, tools are called, and results are managed. While agents make dynamic decisions about what to do, workflows provide the underlying framework that governs how those decisions are executed. -### Understanding Workflows in Agent Systems +### Understanding workflows in agent systems Think of a workflow like the operating procedures of a company. The company (agent) can make various decisions, but how those decisions get implemented follows established processes (workflows). For example, when you book a flight through a travel agent, they might make different decisions about which flights to recommend, but the process of actually booking the flight follows a fixed sequence of steps. Let's examine a basic agent workflow: -### Core Components of a Workflow +### Core components of a workflow A workflow typically consists of several key elements: diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx index a8403420c14b196..35d4e958880fe51 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -18,7 +18,7 @@ Agent state is stored in SQL database that associate with each indidivual Agent ### State API -Every agent has built-in state management capabilities. You can set and update the agent's state directly using `this.setState`: +Every Agent has built-in state management capabilities. You can set and update the Agent's state directly using `this.setState`: @@ -95,7 +95,7 @@ Clients can connect to an Agent and stay synchronized with its state using the R The state synchronization system: -* Automatically syncs the agent's state to all connected clients +* Automatically syncs the Agent's state to all connected clients * Handles client disconnections and reconnections gracefully * Provides immediate local updates * Supports multiple simultaneous client connections @@ -106,7 +106,7 @@ Common use cases: * Multi-window/tab synchronization * Live updates across multiple devices * Maintaining consistent UI state across clients -* When new clients connect, they automatically receive the current state from the agent, ensuring all clients start with the latest data. +* When new clients connect, they automatically receive the current state from the Agent, ensuring all clients start with the latest data. ### SQL API diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index 8614e3f96dff631..3f6b78c28655cfa 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -66,11 +66,11 @@ Tasks that set a callback for a method that does not exist will fail silently. ::: -Calling `await this.schedule` returns a `Schedule`, which includes the task's randomly generated `id`. You can use this `id` to retrieve or cancel the task in the future. It also provides a `type` property that indicates the type of schedule - e.g. one of `"scheduled" | "delayed" | "cron"`. +Calling `await this.schedule` returns a `Schedule`, which includes the task's randomly generated `id`. You can use this `id` to retrieve or cancel the task in the future. It also provides a `type` property that indicates the type of schedule, for example, one of `"scheduled" | "delayed" | "cron"`. :::note[Maximum scheduled tasks] -Each task is mapped to a row in the Agent's underlying [SQLite database](/sqlite-in-durable-objects/), which means that each task can be up to 2MB in size. The maximum number of tasks must be `(task_size * tasks) + all_other_state < maximum_database_size` (currently 1GB per Agent). +Each task is mapped to a row in the Agent's underlying [SQLite database](/sqlite-in-durable-objects/), which means that each task can be up to 2 MB in size. The maximum number of tasks must be `(task_size * tasks) + all_other_state < maximum_database_size` (currently 1GB per Agent). ::: diff --git a/src/content/docs/agents/examples/using-ai-models.mdx b/src/content/docs/agents/examples/using-ai-models.mdx index 3db4d39bcaf5948..cfd85b2e536700a 100644 --- a/src/content/docs/agents/examples/using-ai-models.mdx +++ b/src/content/docs/agents/examples/using-ai-models.mdx @@ -8,9 +8,9 @@ sidebar: import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -Agents can communicate with AI models hosted on any provider, including [Workers AI](/workers-ai/), OpenAI, Anthropic and Google's Gemini. +Agents can communicate with AI models hosted on any provider, including [Workers AI](/workers-ai/), OpenAI, Anthropic, and Google's Gemini. -Because Agents are built on top of [Durable Objects](/durable-objects/), each agent or chat session is associated with a stateful compute instance. Tradtional serverless architectures often present challenges for persistent connections needed in real-time applications like chat. +Because Agents are built on top of [Durable Objects](/durable-objects/), each Agent or chat session is associated with a stateful compute instance. Tradtional serverless architectures often present challenges for persistent connections needed in real-time applications like chat. A user can disconnect during a long-running response from a modern reasoning model (such as `o3-mini` or DeepSeek R1), or lose conversational context when refreshing the browser. Instead of relying on request-response patterns and managing an external database to track & store conversation state, state can be stored directly within the Agent. If a client disconnects, the Agent can write to its own distributed storage, and catch the client up as soon as it reconnects: even if it's hours or days later. diff --git a/src/content/docs/agents/examples/websockets.mdx b/src/content/docs/agents/examples/websockets.mdx index d113e8d117cf8c4..7780270fa50011d 100644 --- a/src/content/docs/agents/examples/websockets.mdx +++ b/src/content/docs/agents/examples/websockets.mdx @@ -12,7 +12,7 @@ Users and clients can connect to an Agent directly over WebSockets, allowing lon To enable an Agent to accept WebSockets, define `onConnect` and `onMessage` methods on your Agent. -* `onConnect(connection: Connection, ctx: ConnectionContext)` is called when a client establishes a new WebSocket connection. The original HTTP request, including request headers, cookies and the URL itself, are available on `ctx.request`. +* `onConnect(connection: Connection, ctx: ConnectionContext)` is called when a client establishes a new WebSocket connection. The original HTTP request, including request headers, cookies, and the URL itself, are available on `ctx.request`. * `onMessage(connection: Connection, message: WSMessage)` is called for each incoming WebSocket message. Messages are one of `ArrayBuffer | ArrayBufferView | string`, and you can send messages back to a client using `connection.send()`. You can distinguish between client connections by checking `connection.id`, which is unique for each connected client. Here's an example of an Agent that echoes back any message it receives: @@ -55,7 +55,7 @@ export class ChatAgent extends Agent { ## Connecting clients -The Agent framework includes a useful helper package for connecting directly to your agent (or other agents) from a client application. Import `@cloudflare/agents/client`, create an instance of `AgentClient` and use it to connect to an instance of your Agent: +The Agent framework includes a useful helper package for connecting directly to your Agent (or other Agents) from a client application. Import `@cloudflare/agents/client`, create an instance of `AgentClient` and use it to connect to an instance of your Agent: @@ -120,7 +120,7 @@ function AgentInterface() { ``` -The `useAgent` hook automatically handles the lifecycle of the connection, ensuring that it is properly initialized and cleaned up when the component mounts and unmounts. You can also [combine `useAgent` with `useState`](/agents/examples/manage-and-sync-state/) to automatically synchronize state across all clients connected to your agent. +The `useAgent` hook automatically handles the lifecycle of the connection, ensuring that it is properly initialized and cleaned up when the component mounts and unmounts. You can also [combine `useAgent` with `useState`](/agents/examples/manage-and-sync-state/) to automatically synchronize state across all clients connected to your Agent. ## Handling WebSocket events diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index 5acd1a2b29e2127..b46236682dac16b 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -49,7 +49,7 @@ TODO - refine args={"--", "--template", "cloudflare/agents/starter"} /> -Head to the [Agents tutorial[(/getting-started/tutorial/) to dive into shipping your first Agent on Cloudflare. +Head to the [Agents tutorial[(/agents/getting-started/tutorial/) to dive into shipping your first Agent on Cloudflare. ## Agents platform diff --git a/src/content/docs/agents/reference/agents-vs-workflows.mdx b/src/content/docs/agents/reference/agents-vs-workflows.mdx index 1edcde47e8c8922..85ca6a07798e00d 100644 --- a/src/content/docs/agents/reference/agents-vs-workflows.mdx +++ b/src/content/docs/agents/reference/agents-vs-workflows.mdx @@ -7,7 +7,7 @@ sidebar: import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; -When should build an Agent vs a Workflow? +When should you build an Agent vs a Workflow? | Problem to Solve | Agent | Workflows | |---|---|---| diff --git a/src/content/docs/agents/reference/limits.mdx b/src/content/docs/agents/reference/limits.mdx index 3ae7cad80876da8..c778b91216eddc3 100644 --- a/src/content/docs/agents/reference/limits.mdx +++ b/src/content/docs/agents/reference/limits.mdx @@ -18,14 +18,14 @@ Many limits are inherited from those applied to Workers scripts and/or Durable O | ----------------------------------------- | ----------------------- | | Max concurrent (running) Agents per account | Tens of millions+ [^1] | Max definitions per account | ~250,000+ [^2] -| Max state stored per unique Agent | 1GB | +| Max state stored per unique Agent | 1 GB | | Max compute time per Agent | 30 seconds (refreshed per HTTP request / incoming WebSocket message) [^3] | | Duration (wall clock) per step [^3] | Unlimited (e.g. waiting on a database call or an LLM response) | --- [^1]: Yes, really. You can have tens of millions of Agents running concurrently, as each Agent is mapped to a [unique Durable Object](/durable-objects/what-are-durable-objects/) (actor). -[^2]: You can deploy up to [500 scripts per account](/workers/platform/limits/), but each script (project) can define multiple Agents. Each deployed script can be up to 10MB on the [Workers Paid Plan](/workers/platform/pricing/#workers) +[^2]: You can deploy up to [500 scripts per account](/workers/platform/limits/), but each script (project) can define multiple Agents. Each deployed script can be up to 10 MB on the [Workers Paid Plan](/workers/platform/pricing/#workers) [^3]: Compute (CPU) time per Agent is limited to 30 seconds, but this is refreshed when an Agent receives a new HTTP request, runs a [scheduled task](/agents/examples/schedule-tasks/), or an incoming WebSocket message. From 99cbca47acd86035f54af0666b571b4051d542ff Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 13:03:50 -0500 Subject: [PATCH 16/41] fix sidebar ordering --- src/content/docs/agents/api-reference/index.mdx | 3 +-- src/content/docs/agents/building-with-ai/index.mdx | 2 +- src/content/docs/agents/concepts/index.mdx | 2 +- src/content/docs/agents/examples/index.mdx | 4 ++-- src/content/docs/agents/examples/manage-and-sync-state.mdx | 7 ++++--- src/content/docs/agents/getting-started/index.mdx | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/content/docs/agents/api-reference/index.mdx b/src/content/docs/agents/api-reference/index.mdx index a11a64bb8f59f7b..cec0accbc24572c 100644 --- a/src/content/docs/agents/api-reference/index.mdx +++ b/src/content/docs/agents/api-reference/index.mdx @@ -2,10 +2,9 @@ title: Agents API Reference pcx_content_type: navigation sidebar: - order: 3 + order: 5 group: hideIndex: true - --- import { DirectoryListing } from "~/components" diff --git a/src/content/docs/agents/building-with-ai/index.mdx b/src/content/docs/agents/building-with-ai/index.mdx index cfb5f75f9dd48bf..fab8c7a29d2dc9b 100644 --- a/src/content/docs/agents/building-with-ai/index.mdx +++ b/src/content/docs/agents/building-with-ai/index.mdx @@ -2,7 +2,7 @@ title: Building with AI pcx_content_type: navigation sidebar: - order: 5 + order: 4 group: hideIndex: true diff --git a/src/content/docs/agents/concepts/index.mdx b/src/content/docs/agents/concepts/index.mdx index f0c26ca975dc153..2f115caf1042468 100644 --- a/src/content/docs/agents/concepts/index.mdx +++ b/src/content/docs/agents/concepts/index.mdx @@ -2,7 +2,7 @@ pcx_content_type: reference title: Concepts sidebar: - order: 1 + order: 2 group: hideIndex: true --- diff --git a/src/content/docs/agents/examples/index.mdx b/src/content/docs/agents/examples/index.mdx index 653759643e4a623..34f41dbf12ee2ec 100644 --- a/src/content/docs/agents/examples/index.mdx +++ b/src/content/docs/agents/examples/index.mdx @@ -1,8 +1,8 @@ --- pcx_content_type: reference -title: Build +title: Examples sidebar: - order: 4 + order: 3 --- import { DirectoryListing, PackageManagers } from "~/components"; diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx index 35d4e958880fe51..4c4278e6935e870 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -144,14 +144,15 @@ export class MyAgent extends Agent { async onRequest(request: Request) { let userId = new URL(request.url).searchParams.get('userId'); // Supply the type paramter to the query when calling this.sql - // This assumes the results return a single User row with "id", "name", and "email" columns - // You can also pass an array as the type argument to the query - e.g. User[] + // This assumes the results returns one or more User rows with "id", "name", and "email" columns const user = await this.sql`SELECT * FROM users WHERE id = ${userId}`; return Response.json(user) } } ``` +You do not need to specify an array type (`User[]` or `Array`) as `this.sql` will always return an array of the specified type. + Providing a type parameter does not validate that the result matches your type definition. In TypeScript, properties (fields) that do not exist or conform to the type you provided will be dropped. If you need to validate incoming events, we recommend a library such as [zod](https://zod.dev/) or your own validator logic. :::note @@ -160,4 +161,4 @@ Learn more about the zero-latency SQL storage that powers both Agents and Durabl ::: -The SQL API exposed to an Agent is similar to the one [within Durable Objects](/durable-objects/api/sql-storage/). This means that you can use the same SQL queries with the Agent's database, create tables, and query data. +The SQL API exposed to an Agent is similar to the one [within Durable Objects](/durable-objects/api/sql-storage/): Durable Object SQL methods available on `this.ctx.storage.sql`. You can use the same SQL queries with the Agent's database, create tables, and query data, as you would with Durable Objects or D1, as the dialect is the same. diff --git a/src/content/docs/agents/getting-started/index.mdx b/src/content/docs/agents/getting-started/index.mdx index 0130d074d144e20..d3a068f800f2789 100644 --- a/src/content/docs/agents/getting-started/index.mdx +++ b/src/content/docs/agents/getting-started/index.mdx @@ -2,7 +2,7 @@ title: Getting started pcx_content_type: navigation sidebar: - order: 2 + order: 1 group: hideIndex: true From afc175d21ff5ab664192bc2746f0abfa5150e169 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 13:08:50 -0500 Subject: [PATCH 17/41] fix sidebar --- .../docs/agents/api-reference/index.mdx | 2 +- .../agents/building-with-ai/prompting.mdx | 1028 ----------------- .../{building-with-ai => guides}/index.mdx | 3 +- .../agents-vs-workflows.mdx | 0 .../agents/{reference => platform}/index.mdx | 0 .../agents/{reference => platform}/limits.mdx | 2 +- .../llms.txt.mdx | 2 +- .../docs/agents/platform/prompting.mdx | 9 + 8 files changed, 13 insertions(+), 1033 deletions(-) delete mode 100644 src/content/docs/agents/building-with-ai/prompting.mdx rename src/content/docs/agents/{building-with-ai => guides}/index.mdx (86%) rename src/content/docs/agents/{reference => platform}/agents-vs-workflows.mdx (100%) rename src/content/docs/agents/{reference => platform}/index.mdx (100%) rename src/content/docs/agents/{reference => platform}/limits.mdx (99%) rename src/content/docs/agents/{building-with-ai => platform}/llms.txt.mdx (93%) create mode 100644 src/content/docs/agents/platform/prompting.mdx diff --git a/src/content/docs/agents/api-reference/index.mdx b/src/content/docs/agents/api-reference/index.mdx index cec0accbc24572c..3db3271d4f644a3 100644 --- a/src/content/docs/agents/api-reference/index.mdx +++ b/src/content/docs/agents/api-reference/index.mdx @@ -1,5 +1,5 @@ --- -title: Agents API Reference +title: API Reference pcx_content_type: navigation sidebar: order: 5 diff --git a/src/content/docs/agents/building-with-ai/prompting.mdx b/src/content/docs/agents/building-with-ai/prompting.mdx deleted file mode 100644 index a5416bbf223a213..000000000000000 --- a/src/content/docs/agents/building-with-ai/prompting.mdx +++ /dev/null @@ -1,1028 +0,0 @@ ---- -title: Prompting AI Models -pcx_content_type: concept -sidebar: - order: 101 ---- - -import { Tabs, TabItem, GlossaryTooltip, Type, Badge, TypeScriptExample } from "~/components"; - -## Prompting - -When building, iterating on or debugging applications using AI tools and Large Language Models (LLMs), a well-structured and extensive prompt helps provide the model with clearer guidelines & examples that can dramatically improve output. - -We're providing an extensive example prompt that can help you build apps and AI agents using Cloudflare Workers and your preferred AI model. - -Use the click-to-copy button at the top right of the code block below to copy the full prompt to your clipboard: - -```md collapse={30-10000} - -You are an advanced assistant specialized in generating Cloudflare Workers code. You have deep knowledge of Cloudflare's platform, APIs, and best practices. - - - - -- Respond in a friendly and concise manner -- Focus exclusively on Cloudflare Workers solutions -- Provide complete, self-contained solutions -- Default to current best practices -- Ask clarifying questions when requirements are ambiguous - - - - - -- Generate code in TypeScript by default unless JavaScript is specifically requested -- Use ES modules format exclusively (never use Service Worker format) -- You SHALL keep all code in a single file unless otherwise specified -- Minimize external dependencies, unless there is an official SDK or library for the service you are integrating with, then use it to simplify the implementation. -- Do not use libraries that have FFI/native/C bindings. -- Follow Cloudflare Workers security best practices -- Never bake in secrets into the code -- Include proper error handling and logging -- Add appropriate TypeScript types and interfaces -- Include comments explaining complex logic - - - - - -- Use markdown code blocks to separate code from explanations -- Provide separate blocks for: - 1. Main worker code (index.ts/index.js) - 2. Configuration (wrangler.jsonc) - 3. Type definitions (if applicable) - 4. Example usage/tests -- Always output complete files, never partial updates or diffs -- Format code consistently using standard TypeScript/JavaScript conventions - - - - - -- When data storage is needed, integrate with appropriate Cloudflare services: - - Workers KV for key-value storage, including configuration data, user profiles, and A/B testing - - Durable Objects for strongly consistent state management, storage, and multiplayer co-ordination use-cases - - D1 for relational data and for its SQL dialect - - R2 for object storage, including storing structured data, AI assets, image assets and for user-facing uploads - - Hyperdrive to connect to existing (PostgreSQL) databases that a developer may already have - - Queues for asynchronous processing and background tasks - - Vectorize for storing embeddings and to support vector search (often in combination with Workers AI) - - Workers Analytics Engine for tracking user events, billing, metrics and high-cardinality analytics - - Workers AI as the default AI API for inference requests. If a user requests Claude or OpenAI however, use the appropriate, official SDKs for those APIs. - - Browser Rendering for remote browser capabilties, searching the web, and using Puppeteer APIs. -- Include all necessary bindings in both code and wrangler.jsonc -- Add appropriate environment variable definitions - - - - - -- Always provide a wrangler.jsonc (not wrangler.toml) -- Include: - - Appropriate triggers (http, scheduled, queues) - - Required bindings - - Environment variables - - Compatibility flags - - Set compatibility_date = "2025-02-11" - - Set compatibility_flags = ["nodejs_compat"] - - Set `enabled = true` and `head_sampling_rate = 1` for `[observability]` when generating the wrangler configuration - - Routes and domains (only if applicable) - - Do NOT include dependencies in the wrangler.jsonc file - - Only include bindings that are used in the code - - - -// wrangler.jsonc -{ - "name": "app-name-goes-here", // name of the app - "main": "src/index.ts", // default file - "compatibility_date": "2025-02-11", - "compatibility_flags": ["nodejs_compat"], // Enable Node.js compatibility - "observability": { - // Enable logging by default - "enabled": true, - } -} - - - - - - Defines a name for the app the user is building - - Sets `src/index.ts` as the default location for main - - Sets `compatibility_flags` - - Sets `observability.enabled = true` - - - - - - - -- Implement proper request validation -- Use appropriate security headers -- Handle CORS correctly when needed -- Implement rate limiting where appropriate -- Follow least privilege principle for bindings -- Sanitize user inputs - - - - - -- Include basic test examples -- Provide curl commands for API endpoints -- Add example environment variable values -- Include sample requests and responses - - - - - -- Optimize for cold starts -- Minimize unnecessary computation -- Use appropriate caching strategies -- Consider Workers limits and quotas -- Implement streaming where beneficial - - - - - -- Implement proper error boundaries -- Return appropriate HTTP status codes -- Provide meaningful error messages -- Log errors appropriately -- Handle edge cases gracefully - - - - - -- Always use WebSocket Hibernation API instead of legacy WebSocket API unless otherwise specified -- You SHALL use the Durable Objects WebSocket Hibernation API when providing WebSocket handling code within a Durable Object. - Refer to for an example implementation. -- Use `this.ctx.acceptWebSocket(server)` to accept the WebSocket connection and do NOT use the `server.accept()` method. -- Define an `async webSocketMessage()` handler that is invoked when a message is received from the client -- Define an `async webSocketClose()` handler that is invoked when the WebSocket connection is closed -- Do NOT use the `addEventListener` pattern to handle WebSocket events. -- Handle WebSocket upgrade requests explicitly - - - - - - - -Example of using the Hibernatable WebSocket API in Durable Objects to handle WebSocket connections. - - - -import { DurableObject } from "cloudflare:workers"; - -interface Env { -WEBSOCKET_HIBERNATION_SERVER: DurableObject; -} - -// Durable Object -export class WebSocketHibernationServer extends DurableObject { -async fetch(request) { -// Creates two ends of a WebSocket connection. -const webSocketPair = new WebSocketPair(); -const [client, server] = Object.values(webSocketPair); - - // Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating - // request within the Durable Object. It has the effect of "accepting" the connection, - // and allowing the WebSocket to send and receive messages. - // Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket - // is "hibernatable", so the runtime does not need to pin this Durable Object to memory while - // the connection is open. During periods of inactivity, the Durable Object can be evicted - // from memory, but the WebSocket connection will remain open. If at some later point the - // WebSocket receives a message, the runtime will recreate the Durable Object - // (run the `constructor`) and deliver the message to the appropriate handler. - this.ctx.acceptWebSocket(server); - - return new Response(null, { - status: 101, - webSocket: client, - }); - - }, - - async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void | Promise { - // Upon receiving a message from the client, reply with the same message, - // but will prefix the message with "[Durable Object]: " and return the - // total number of connections. - ws.send( - `[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`, - ); - }, - - async webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean) void | Promise { - // If the client closes the connection, the runtime will invoke the webSocketClose() handler. - ws.close(code, "Durable Object is closing WebSocket"); - }, - - async webSocketError(ws: WebSocket, error: unknown): void | Promise { - console.error("WebSocket error:", error); - ws.close(1011, "WebSocket error"); - } - -} - - - - -{ - "name": "websocket-hibernation-server", - "durable_objects": { - "bindings": [ - { - "name": "WEBSOCKET_HIBERNATION_SERVER", - "class_name": "WebSocketHibernationServer" - } - ] - }, - "migrations": [ - { - "tag": "v1", - "new_classes": ["WebSocketHibernationServer"] - } - ] -} - - - - -- Uses the WebSocket Hibernation API instead of the legacy WebSocket API -- Calls `this.ctx.acceptWebSocket(server)` to accept the WebSocket connection -- Has a `webSocketMessage()` handler that is invoked when a message is received from the client -- Has a `webSocketClose()` handler that is invoked when the WebSocket connection is closed -- Does NOT use the `server.addEventListener` API unless explicitly requested. -- Don't over-use the "Hibernation" term in code or in bindings. It is an implementation detail. - - - - - -Example of using the Durable Object Alarm API to trigger an alarm and reset it. - - - -import { DurableObject } from "cloudflare:workers"; - -interface Env { -ALARM_EXAMPLE: DurableObject; -} - -export default { - async fetch(request, env) { - let url = new URL(request.url); - let userId = url.searchParams.get("userId") || crypto.randomUUID(); - let id = env.ALARM_EXAMPLE.idFromName(userId); - return await env.ALARM_EXAMPLE.get(id).fetch(request); - }, -}; - -const SECONDS = 1000; - -export class AlarmExample extends DurableObject { -constructor(ctx, env) { -this.ctx = ctx; -this.storage = ctx.storage; -} -async fetch(request) { -// If there is no alarm currently set, set one for 10 seconds from now -let currentAlarm = await this.storage.getAlarm(); -if (currentAlarm == null) { -this.storage.setAlarm(Date.now() + 10 \_ SECONDS); -} -} -async alarm(alarmInfo) { -// The alarm handler will be invoked whenever an alarm fires. -// You can use this to do work, read from the Storage API, make HTTP calls -// and set future alarms to run using this.storage.setAlarm() from within this handler. -if (alarmInfo?.retryCount != 0) { -console.log("This alarm event has been attempted ${alarmInfo?.retryCount} times before."); -} - -// Set a new alarm for 10 seconds from now before exiting the handler -this.storage.setAlarm(Date.now() + 10 \_ SECONDS); -} -} - - - - -{ - "name": "durable-object-alarm", - "durable_objects": { - "bindings": [ - { - "name": "ALARM_EXAMPLE", - "class_name": "DurableObjectAlarm" - } - ] - }, - "migrations": [ - { - "tag": "v1", - "new_classes": ["DurableObjectAlarm"] - } - ] -} - - - - -- Uses the Durable Object Alarm API to trigger an alarm -- Has a `alarm()` handler that is invoked when the alarm is triggered -- Sets a new alarm for 10 seconds from now before exiting the handler - - - - - -Using Workers KV to store session data and authenticate requests, with Hono as the router and middleware. - - - -// src/index.ts -import { Hono } from 'hono' -import { cors } from 'hono/cors' - -interface Env { -AUTH_TOKENS: KVNamespace; -} - -const app = new Hono<{ Bindings: Env }>() - -// Add CORS middleware -app.use('\*', cors()) - -app.get('/', async (c) => { -try { -// Get token from header or cookie -const token = c.req.header('Authorization')?.slice(7) || -c.req.header('Cookie')?.match(/auth_token=([^;]+)/)?.[1]; -if (!token) { -return c.json({ -authenticated: false, -message: 'No authentication token provided' -}, 403) -} - - // Check token in KV - const userData = await c.env.AUTH_TOKENS.get(token) - - if (!userData) { - return c.json({ - authenticated: false, - message: 'Invalid or expired token' - }, 403) - } - - return c.json({ - authenticated: true, - message: 'Authentication successful', - data: JSON.parse(userData) - }) - -} catch (error) { -console.error('Authentication error:', error) -return c.json({ -authenticated: false, -message: 'Internal server error' -}, 500) -} -}) - -export default app - - - -{ - "name": "auth-worker", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "kv_namespaces": [ - { - "binding": "AUTH_TOKENS", - "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", - "preview_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - } - ] -} - - - - -- Uses Hono as the router and middleware -- Uses Workers KV to store session data -- Uses the Authorization header or Cookie to get the token -- Checks the token in Workers KV -- Returns a 403 if the token is invalid or expired - - - - - - -Use Cloudflare Queues to produce and consume messages. - - - -// src/producer.ts -interface Env { - REQUEST_QUEUE: Queue; - UPSTREAM_API_URL: string; - UPSTREAM_API_KEY: string; -} - -export default { -async fetch(request: Request, env: Env) { -const info = { -timestamp: new Date().toISOString(), -method: request.method, -url: request.url, -headers: Object.fromEntries(request.headers), -}; -await env.REQUEST_QUEUE.send(info); - -return Response.json({ -message: 'Request logged', -requestId: crypto.randomUUID() -}); - -}, - -async queue(batch: MessageBatch, env: Env) { -const requests = batch.messages.map(msg => msg.body); - - const response = await fetch(env.UPSTREAM_API_URL, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${env.UPSTREAM_API_KEY}` - }, - body: JSON.stringify({ - timestamp: new Date().toISOString(), - batchSize: requests.length, - requests - }) - }); - - if (!response.ok) { - throw new Error(`Upstream API error: ${response.status}`); - } - -} -}; - - - - -{ - "name": "request-logger-consumer", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "queues": { - "producers": [{ - "name": "request-queue", - "binding": "REQUEST_QUEUE" - }], - "consumers": [{ - "name": "request-queue", - "dead_letter_queue": "request-queue-dlq", - "retry_delay": 300 - }] - }, - "vars": { - "UPSTREAM_API_URL": "https://api.example.com/batch-logs", - "UPSTREAM_API_KEY": "" - } -} - - - - -- Defines both a producer and consumer for the queue -- Uses a dead letter queue for failed messages -- Uses a retry delay of 300 seconds to delay the re-delivery of failed messages -- Shows how to batch requests to an upstream API - - - - - - -Connect to and query a Postgres database using Cloudflare Hyperdrive. - - - -// Postgres.js 3.4.5 or later is recommended -import postgres from "postgres"; - -export interface Env { -// If you set another name in the Wrangler config file as the value for 'binding', -// replace "HYPERDRIVE" with the variable name you defined. -HYPERDRIVE: Hyperdrive; -} - -export default { -async fetch(request, env, ctx): Promise { -console.log(JSON.stringify(env)); -// Create a database client that connects to your database via Hyperdrive. -// -// Hyperdrive generates a unique connection string you can pass to -// supported drivers, including node-postgres, Postgres.js, and the many -// ORMs and query builders that use these drivers. -const sql = postgres(env.HYPERDRIVE.connectionString) - - try { - // Test query - const results = await sql`SELECT * FROM pg_tables`; - - // Clean up the client, ensuring we don't kill the worker before that is - // completed. - ctx.waitUntil(sql.end()); - - // Return result rows as JSON - return Response.json(results); - } catch (e) { - console.error(e); - return Response.json( - { error: e instanceof Error ? e.message : e }, - { status: 500 }, - ); - } - -}, -} satisfies ExportedHandler; - - - - -{ - "name": "hyperdrive-postgres", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "hyperdrive": [ - { - "binding": "HYPERDRIVE", - "id": "" - } - ] -} - - - -// Install Postgres.js -npm install postgres - -// Create a Hyperdrive configuration -npx wrangler hyperdrive create --connection-string="postgres://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name" - - - - - -- Installs and uses Postgres.js as the database client/driver. -- Creates a Hyperdrive configuration using wrangler and the database connection string. -- Uses the Hyperdrive connection string to connect to the database. -- Calling `sql.end()` is optional, as Hyperdrive will handle the connection pooling. - - - - - - -Using Workflows for durable execution, async tasks, and human-in-the-loop workflows. - - - -import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers'; - -type Env = { -// Add your bindings here, e.g. Workers KV, D1, Workers AI, etc. -MY_WORKFLOW: Workflow; -}; - -// User-defined params passed to your workflow -type Params = { -email: string; -metadata: Record; -}; - -export class MyWorkflow extends WorkflowEntrypoint { -async run(event: WorkflowEvent, step: WorkflowStep) { -// Can access bindings on `this.env` -// Can access params on `event.payload` -const files = await step.do('my first step', async () => { -// Fetch a list of files from $SOME_SERVICE -return { -files: [ -'doc_7392_rev3.pdf', -'report_x29_final.pdf', -'memo_2024_05_12.pdf', -'file_089_update.pdf', -'proj_alpha_v2.pdf', -'data_analysis_q2.pdf', -'notes_meeting_52.pdf', -'summary_fy24_draft.pdf', -], -}; -}); - - const apiResponse = await step.do('some other step', async () => { - let resp = await fetch('https://api.cloudflare.com/client/v4/ips'); - return await resp.json(); - }); - - await step.sleep('wait on something', '1 minute'); - - await step.do( - 'make a call to write that could maybe, just might, fail', - // Define a retry strategy - { - retries: { - limit: 5, - delay: '5 second', - backoff: 'exponential', - }, - timeout: '15 minutes', - }, - async () => { - // Do stuff here, with access to the state from our previous steps - if (Math.random() > 0.5) { - throw new Error('API call to $STORAGE_SYSTEM failed'); - } - }, - ); - -} -} - -export default { -async fetch(req: Request, env: Env): Promise { -let url = new URL(req.url); - - if (url.pathname.startsWith('/favicon')) { - return Response.json({}, { status: 404 }); - } - - // Get the status of an existing instance, if provided - let id = url.searchParams.get('instanceId'); - if (id) { - let instance = await env.MY_WORKFLOW.get(id); - return Response.json({ - status: await instance.status(), - }); - } - - const data = await req.json() - - // Spawn a new instance and return the ID and status - let instance = await env.MY_WORKFLOW.create({ - // Define an ID for the Workflow instance - id: crypto.randomUUID(), - // Pass data to the Workflow instance - // Available on the WorkflowEvent - params: data, - }); - - return Response.json({ - id: instance.id, - details: await instance.status(), - }); - -}, -}; - - - - -{ - "name": "workflows-starter", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "workflows": [ - { - "name": "workflows-starter", - "binding": "MY_WORKFLOW", - "class_name": "MyWorkflow" - } - ] -} - - - - -- Defines a Workflow by extending the WorkflowEntrypoint class. -- Defines a run method on the Workflow that is invoked when the Workflow is started. -- Ensures that `await` is used before calling `step.do` or `step.sleep` -- Passes a payload (event) to the Workflow from a Worker -- Defines a payload type and uses TypeScript type arguments to ensure type safety - - - - - - - Using Workers Analytics Engine for writing event data. - - - -interface Env { - USER_EVENTS: AnalyticsEngineDataset; -} - -export default { -async fetch(req: Request, env: Env): Promise { -let url = new URL(req.url); -let path = url.pathname; -let userId = url.searchParams.get("userId"); - - // Write a datapoint for this visit, associating the data with - // the userId as our Analytics Engine 'index' - env.USER_EVENTS.writeDataPoint({ - // Write metrics data: counters, gauges or latency statistics - doubles: [], - // Write text labels - URLs, app names, event_names, etc - blobs: [path], - // Provide an index that groups your data correctly. - indexes: [userId], - }); - - return Response.json({ - hello: "world", - }); - , - -}; - - - - -{ - "name": "analytics-engine-example", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "analytics_engine_datasets": [ - { - "binding": "", - "dataset": "" - } - ] - } -} - - - -// Query data within the 'temperatures' dataset -// This is accessible via the REST API at https://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sql -SELECT - timestamp, - blob1 AS location_id, - double1 AS inside_temp, - double2 AS outside_temp -FROM temperatures -WHERE timestamp > NOW() - INTERVAL '1' DAY - -// List the datasets (tables) within your Analytics Engine -curl "" \ ---header "Authorization: Bearer " \ ---data "SHOW TABLES" - - - - - -- Binds an Analytics Engine dataset to the Worker -- Uses the `AnalyticsEngineDataset` type when using TypeScript for the binding -- Writes event data using the `writeDataPoint` method and writes an `AnalyticsEngineDataPoint` -- Does NOT `await` calls to `writeDataPoint`, as it is non-blocking -- Defines an index as the key representing an app, customer, merchant or tenant. -- Developers can use the GraphQL or SQL APIs to query data written to Analytics Engine - - - - - -Use the Browser Rendering API as a headless browser to interact with websites from a Cloudflare Worker. - - - -import puppeteer from "@cloudflare/puppeteer"; - -interface Env { - BROWSER_RENDERING: Fetcher; -} - -export default { - async fetch(request, env): Promise { - const { searchParams } = new URL(request.url); - let url = searchParams.get("url"); - - if (url) { - url = new URL(url).toString(); // normalize - const browser = await puppeteer.launch(env.MYBROWSER); - const page = await browser.newPage(); - await page.goto(url); - // Parse the page content - const content = await page.content(); - // Find text within the page content - const text = await page.$eval("body", (el) => el.textContent); - // Do something with the text - // e.g. log it to the console, write it to KV, or store it in a database. - console.log(text); - - // Ensure we close the browser session - await browser.close(); - - return Response.json({ - bodyText: text, - }) - } else { - return Response.json({ - error: "Please add an ?url=https://example.com/ parameter" - }, { status: 400 }) - } - }, -} satisfies ExportedHandler; - - - -{ - "name": "browser-rendering-example", - "main": "src/index.ts", - "compatibility_date": "2025-02-11", - "browser": [ - { - "binding": "BROWSER_RENDERING", - } - ] -} - - - -// Install @cloudflare/puppeteer -npm install @cloudflare/puppeteer --save-dev - - - - -- Configures a BROWSER_RENDERING binding -- Passes the binding to Puppeteer -- Uses the Puppeteer APIs to navigate to a URL and render the page -- Parses the DOM and returns context for use in the response -- Correctly creates and closes the browser instance - - - - - - - - - - -Fan-in/fan-out for WebSockets. Uses the Hibernatable WebSockets API within Durable Objects. Does NOT use the legacy addEventListener API. - - -export class WebSocketHibernationServer extends DurableObject { - async fetch(request: Request, env: Env, ctx: ExecutionContext) { - // Creates two ends of a WebSocket connection. - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - // Call this to accept the WebSocket connection. - // Do NOT call server.accept() (this is the legacy approach and is not preferred) - this.ctx.acceptWebSocket(server); - - return new Response(null, { - status: 101, - webSocket: client, - }); -}, - -async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void | Promise { - // Invoked on each WebSocket message. - ws.send(message) -}, - -async webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean) void | Promise { - // Invoked when a client closes the connection. - ws.close(code, ""); -}, - -async webSocketError(ws: WebSocket, error: unknown): void | Promise { - // Handle WebSocket errors -} -} - - - - - -{user_prompt} - -``` - -The prompt above adopts several best practices, including: - -* Using `` tags to structure the prompt -* API and usage examples for products and use-cases -* Guidance on how to generate configuration (e.g. `wrangler.jsonc`) as part of the models response. -* Recommendations on Cloudflare products to use for specific storage or state need - -## Using the prompt - -:::note - -The prompt(s) here are examples and should be adapted to your specific use case. We'll continue to build out the prompts available here, including additional prompts for specific products. - -Depending on the model and user prompt, it may generate invalid code, configuration or other errors, and we recommend reviewing and testing the generated code before deploying it. - -::: - -You can use the prompt in several ways: - -* Within the user context window, with your own user prompt inserted between the `` tags (**easiest**) -* As the `system` prompt for models that support system prompts -* Adding it to the prompt library and/or file context within your preferred IDE: - * Cursor: add the prompt to [your Project Rules](https://docs.cursor.com/context/rules-for-ai) - * Zed: use [the `/file` command](https://zed.dev/docs/assistant/assistant-panel) to add the prompt to the Assistant context. - * Windsurf: use [the `@-mention` command](https://docs.codeium.com/chat/overview) to include a file containing the prompt to your Chat. - -For example, you can use the prompts here with the OpenAI SDK by saving the prompt to a file within your project directory and passing the text to the `system` prompt. - - - -```ts -import workersPrompt from "./workersPrompt.md" - -// Llama 3.3 from Workers AI -const PREFERRED_MODEL = "@cf/meta/llama-3.3-70b-instruct-fp8-fast" - -export default { - async fetch(req: Request, env: Env, ctx: ExecutionContext) { - const openai = new OpenAI({ - apiKey: env.WORKERS_AI_API_KEY - }); - - const stream = await openai.chat.completions.create({ - messages: [ - { - role: "system", - content: workersPrompt, - }, - { - role: "user", - // Imagine something big! - content: "Build an AI Agent using Workflows. The Workflow should be triggered by a GitHub webhook on a pull request, and ..." - } - ], - model: PREFERRED_MODEL, - stream: true, - }); - - // Stream the response so we're not buffering the entire response in memory, - // since it could be very large. - const transformStream = new TransformStream(); - const writer = transformStream.writable.getWriter(); - const encoder = new TextEncoder(); - - (async () => { - try { - for await (const chunk of stream) { - const content = chunk.choices[0]?.delta?.content || ''; - await writer.write(encoder.encode(content)); - } - } finally { - await writer.close(); - } - })(); - - return new Response(transformStream.readable, { - headers: { - 'Content-Type': 'text/plain; charset=utf-8', - 'Transfer-Encoding': 'chunked' - } - }); - } -} - -``` - - - - -## Additional resources - -To get the most out of AI models and tools, we recommend reading the following guides on prompt engineering and structure: - -* OpenAI's [prompt engineering](https://platform.openai.com/docs/guides/prompt-engineering) guide and [best practices](https://platform.openai.com/docs/guides/reasoning-best-practices) for using reasoning models. -* The [prompt engineering](https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview) guide from Anthropic -* Google's [quick start guide](https://services.google.com/fh/files/misc/gemini-for-google-workspace-prompting-guide-101.pdf) for writing effective prompts -* Meta's [prompting documentation](https://www.llama.com/docs/how-to-guides/prompting/) for their Llama model family. -* GitHub's guide for [prompt engineering](https://docs.github.com/en/copilot/using-github-copilot/copilot-chat/prompt-engineering-for-copilot-chat) when using Copilot Chat. diff --git a/src/content/docs/agents/building-with-ai/index.mdx b/src/content/docs/agents/guides/index.mdx similarity index 86% rename from src/content/docs/agents/building-with-ai/index.mdx rename to src/content/docs/agents/guides/index.mdx index fab8c7a29d2dc9b..ff592a9753bea85 100644 --- a/src/content/docs/agents/building-with-ai/index.mdx +++ b/src/content/docs/agents/guides/index.mdx @@ -1,11 +1,10 @@ --- -title: Building with AI +title: Guides pcx_content_type: navigation sidebar: order: 4 group: hideIndex: true - --- import { DirectoryListing } from "~/components" diff --git a/src/content/docs/agents/reference/agents-vs-workflows.mdx b/src/content/docs/agents/platform/agents-vs-workflows.mdx similarity index 100% rename from src/content/docs/agents/reference/agents-vs-workflows.mdx rename to src/content/docs/agents/platform/agents-vs-workflows.mdx diff --git a/src/content/docs/agents/reference/index.mdx b/src/content/docs/agents/platform/index.mdx similarity index 100% rename from src/content/docs/agents/reference/index.mdx rename to src/content/docs/agents/platform/index.mdx diff --git a/src/content/docs/agents/reference/limits.mdx b/src/content/docs/agents/platform/limits.mdx similarity index 99% rename from src/content/docs/agents/reference/limits.mdx rename to src/content/docs/agents/platform/limits.mdx index c778b91216eddc3..be10fa8a1fb9441 100644 --- a/src/content/docs/agents/reference/limits.mdx +++ b/src/content/docs/agents/platform/limits.mdx @@ -2,7 +2,7 @@ pcx_content_type: concept title: Limits sidebar: - order: 4 + order: 1 --- diff --git a/src/content/docs/agents/building-with-ai/llms.txt.mdx b/src/content/docs/agents/platform/llms.txt.mdx similarity index 93% rename from src/content/docs/agents/building-with-ai/llms.txt.mdx rename to src/content/docs/agents/platform/llms.txt.mdx index afee3b4774aed84..9e4d540f2fd35de 100644 --- a/src/content/docs/agents/building-with-ai/llms.txt.mdx +++ b/src/content/docs/agents/platform/llms.txt.mdx @@ -3,7 +3,7 @@ pcx_content_type: navigation title: llms.txt external_link: /llms.txt sidebar: - order: 102 + order: 99 head: [] description: Provide context to your AI models & tools when building on Cloudflare. --- diff --git a/src/content/docs/agents/platform/prompting.mdx b/src/content/docs/agents/platform/prompting.mdx new file mode 100644 index 000000000000000..aef72526d8226e4 --- /dev/null +++ b/src/content/docs/agents/platform/prompting.mdx @@ -0,0 +1,9 @@ +--- +pcx_content_type: navigation +title: Prompt Engineering +external_link: /workers/get-started/prompting/ +sidebar: + order: 98 +head: [] +description: Learn how to prompt engineer your AI models & tools when building Agents & Workers on Cloudflare. +--- From 51c6167868ada3ab13cf86e7d574a6de70383e1a Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 13:22:14 -0500 Subject: [PATCH 18/41] state --- .../agents/examples/manage-and-sync-state.mdx | 15 +++++++++++++-- .../docs/agents/examples/schedule-tasks.mdx | 12 ++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx index 4c4278e6935e870..c20c47fb122d4b4 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -62,7 +62,7 @@ import { Agent } from "@cloudflare/agents"; interface Env {} -// +// Define a type for your Agent's state interface FlightRecord { id: string; departureIata: string; @@ -73,7 +73,18 @@ interface FlightRecord { // Pass in the type of your Agent's state export class MyAgent extends Agent { - // This allows this.setState and + // This allows this.setState and the onStateUpdate method to + // be typed: + async onStateUpdate(state: FlightRecord) { + console.log("state updated", state); + } + + async someOtherMethod() { + this.setState({ + ...this.state, + price: this.state.price + 10, + }); + } } ``` diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index 3f6b78c28655cfa..bf742a4cb72bb1f 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -37,6 +37,12 @@ export class SchedulingAgent extends Agent { ``` +:::caution + +Tasks that set a callback for a method that does not exist wil throw an exception. + +::: + You can schedule tasks in multiple ways: @@ -60,12 +66,6 @@ this.cancelSchedule(task.id); -:::caution - -Tasks that set a callback for a method that does not exist will fail silently. - -::: - Calling `await this.schedule` returns a `Schedule`, which includes the task's randomly generated `id`. You can use this `id` to retrieve or cancel the task in the future. It also provides a `type` property that indicates the type of schedule, for example, one of `"scheduled" | "delayed" | "cron"`. :::note[Maximum scheduled tasks] From 4b9864acb55baf58936d00244fc01d99e1d7a8e1 Mon Sep 17 00:00:00 2001 From: Rita Kozlov Date: Mon, 24 Feb 2025 14:23:24 -0500 Subject: [PATCH 19/41] update overview --- src/content/docs/agents/index.mdx | 488 +----------------------------- 1 file changed, 10 insertions(+), 478 deletions(-) diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index b46236682dac16b..040a93af60eb799 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -23,25 +23,17 @@ import { Tabs, } from "~/components"; -Build and deploy AI-powered agents that can autonomously perform tasks, persist state, browse the web, query data and communicate back to users in real-time over any channel. +Build and deploy AI-powered [agents](~/concepts/agents/) that can autonomously perform tasks, persist state, browse the web, query data and communicate back to users in real-time over any channel. -TODO: - -- "/agents is the docs for the agents platform" -- agents.cloudflare.com / agents.workers.dev (?) -- vibe check: need to signal on DO pricing - -## Why ship an Agent on Cloudflare? - -TODO - refine +### Why builds agents on Cloudflare? - **Batteries included**: Want your agent to search the web? Connect it to [Browser Rendering](/browser-rendering/). Store data? Write to the Agent's underlying [Durable Object](/workers/durable-objects/). Query your database? Connect it to your Postgres database [with Hyperdrive](/hyperdrive/). Stream data back in real-time to one, ten or one thousand users at once? Establish a [WebSocket](/workers/websockets/). Feed data to an AI model? Connect it to [Workers AI](/workers-ai/), OpenAI, Gemini, or Anthropic. - **Scale to production**: Deploy agents to Cloudflare's global network and let them scale out automatically. - **Don't break the bank**: Agents are built on Cloudflare Workers. Only pay when your agents are running. -## Start building - +### Start building +Use the agent started template to bootstrap your first agent: -Head to the [Agents tutorial[(/agents/getting-started/tutorial/) to dive into shipping your first Agent on Cloudflare. - -## Agents platform - - - - -Build agents that can execute complex tasks, progressively save state, and call out to _any_ third party API they need to using [Workflows](/workflows/). Send emails or [text messages](/workflows/examples/twilio/), [browse the web](/browser-rendering/), process and summarize documents, and/or query your database. - -```sh -npm create cloudflare@latest workflows-starter -- --template "cloudflare/workflows-starter" -cd workflows-starter -npm i resend -``` - -```ts collapse={30-1000} -import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers'; -import { Resend } from 'resend'; - -type Env = { - MY_WORKFLOW: Workflow; - RESEND_API_KEY: string; -}; - -type Params = { - email: string; - metadata: Record; -}; - -export class MyWorkflow extends WorkflowEntrypoint { - async run(event: WorkflowEvent, step: WorkflowStep) { - - const files = await step.do('my first step', async () => { - // Fetch a list of files from $SOME_SERVICE - return { - files: [ - 'doc_7392_rev3.pdf', - 'report_x29_final.pdf', - 'memo_2024_05_12.pdf', - 'file_089_update.pdf', - 'proj_alpha_v2.pdf', - 'data_analysis_q2.pdf', - 'notes_meeting_52.pdf', - 'summary_fy24_draft.pdf', - ], - }; - }); - - const summaries = await step.do('summarize text', async () => { - const results = {}; - for (const filename of files.files) { - const fileContent = await this.env.MY_BUCKET.get(filename); - if (!fileContent) continue; - - const text = await fileContent.text(); - const summary = await this.env.WORKERS_AI.run('@cf/meta/llama-3.2-3b-instruct', { - messages: [{ - role: 'user', - content: `Please summarize the following text concisely: ${text}` - }] - }); - results[filename] = summary.response; - } - return results; - }); - - await step.sleep('wait on something', '1 minute'); - - let summaryKey = await step.do( - 'store summaries in R2', - async () => { - const summaryKey = `summaries-${Date.now()}.json`; - await this.env.MY_BUCKET.put(summaryKey, JSON.stringify(summaries)); - return summaryKey; - }, - ); - - await step.do( - 'email summaries', - { - retries: { - limit: 3, - delay: '5 second', - backoff: 'exponential', - } - }, - async () => { - const summaryText = Object.entries(summaries) - .map(([filename, summary]) => `${filename}:\n${summary}\n\n`) - .join(''); - - const resend = new Resend(this.env.RESEND_API_KEY); - - await resend.emails.send({ - from: 'notifications@yourdomain.com', - to: event.payload.email, - subject: 'Your Document Summaries', - text: summaryText, - }); - } - ); - - return summaryKey; - } -} - -export default { - async fetch(req: Request, env: Env): Promise { - let id = new URL(req.url).searchParams.get('instanceId'); - - if (id) { - let instance = await env.MY_WORKFLOW.get(id); - return Response.json({ - status: await instance.status(), - }); - } - - let instance = await env.MY_WORKFLOW.create(); - return Response.json({ - id: instance.id, - details: await instance.status(), - }); - }, -}; -``` - - - - -Use [Durable Objects](/durable-objects/) — stateful, serverless, long-running micro-servers — to ship interactive, real-time agents that can connect to the latest AI models. - -Stream responses over [WebSockets](/durable-objects/best-practices/websockets/), and don't time out while waiting for the latest chain-of-thought models — including `o1` or `deepseek-r1` — to respond. - -```ts -npm i openai -``` - -```ts collapse={30-1000} -import { DurableObject } from "cloudflare:workers"; - -export interface Env { - DURABLE_AGENT: DurableObjectNamespace; - OPENAI_API_KEY: string; -} - -export default { - async fetch(request: Request, env: Env, ctx: ExecutionContext) { - if (request.url.endsWith("/agent/chat")) { - const upgradeHeader = request.headers.get("Upgrade"); - if (!upgradeHeader || upgradeHeader !== "websocket") { - return Response.json( - { error: "Durable Object expected Upgrade: websocket" }, - { status: 426 } - ); - } - - const url = new URL(request.url); - const agentId = url.searchParams.get("id") || (await crypto.randomUUID()); - - let id = env.DURABLE_AGENT.idFromName(agentId); - let agent = env.DURABLE_AGENT.get(id); - - return agent.fetch(request); - } - - return Response.json({ message: "Bad Request" }, { status: 400 }); - }, -}; - -export class DurableAgent extends DurableObject { - constructor(private state: DurableObjectState, private env: Env) { - super(); - } - - async fetch(request: Request): Promise { - const webSocketPair = new WebSocketPair(); - const [client, server] = Object.values(webSocketPair); - - this.ctx.acceptWebSocket(server); - - return new Response(null, { - status: 101, - webSocket: client, - }); - } - - async webSocketMessage(ws: WebSocket, message: ArrayBuffer | string) { - try { - const openai = new OpenAI({ - apiKey: this.env.OPENAI_API_KEY, - timeout: 10 * 60 * 1000, // Don't let it think TOO long. - }); - - // Stream the response to immediately start sending chunks to the client, - // rather than buffering the entire response and making the user wait - const stream = await openai.chat.completions.create({ - model: "o1", - messages: [{ role: "user", content: message.toString() }], - stream: true, - }); - - for await (const chunk of stream) { - const content = chunk.choices[0]?.delta?.content; - if (content) { - ws.send(content); - } - } - } catch (error) { - ws.send( - JSON.stringify({ - error: "OpenAI request failed", - message: error.message, - }) - ); - } - } - - async webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean) { - ws.close(code, "Durable Object is closing WebSocket"); - } -} -``` - - - - -Use the [Browser Rendering API](/browser-rendering/) to allow your agents to search the web, take screenshots, and directly interact with websites. - -```sh -npm install @cloudflare/puppeteer --save-dev -``` - -```ts collapse={30-1000} -import puppeteer from "@cloudflare/puppeteer"; - -interface Env { - MYBROWSER: Fetcher; - BROWSER_KV_DEMO: KVNamespace; -} - -export default { - async fetch(request: Request, env: Env): Promise { - const { searchParams } = new URL(request.url); - const url = searchParams.get("url"); - - if (!url) { - return new Response("Please add an ?url=https://example.com/ parameter"); - } - - const normalizedUrl = new URL(url).toString(); - let img = await env.BROWSER_KV_DEMO.get(normalizedUrl, { type: "arrayBuffer" }); - - if (img === null) { - const browser = await puppeteer.launch(env.MYBROWSER); - const page = await browser.newPage(); - await page.goto(normalizedUrl); - img = await page.screenshot() as Buffer; - - await env.BROWSER_KV_DEMO.put(normalizedUrl, img, { - expirationTtl: 60 * 60 * 24, // 24 hours - }); - - await browser.close(); - } - - return new Response(img, { - headers: { - "content-type": "image/jpeg", - }, - }); - }, -}; -``` - - - - -Use [AI Gateway](/ai-gateway/) to cache, log, retry and run [evals](/ai-gateway/evaluations/) (evaluations) for your agents, no matter where they're deployed. - -```py collapse={30-1000} -from anthropic import Anthropic - -anthropic = Anthropic( - api_key="", - # Route, cache, fallback and log prompt-response pairs between your app - # and your AI model provider. - base_url="https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/anthropic" -) - -message = anthropic.messages.create( - model="claude-3-opus-20240229", - max_tokens=1000, - messages=[{ - "role": "user", - "content": "Generate a Cloudflare Worker that returns a simple JSON payload based on a query param", - }] -) - -print(message.content) -``` - - - - -## Use your favorite AI framework - -Build agents using your favorite AI frameworks, and deploy it directly to [Cloudflare Workers](/workers/). - - - - -Use [LangChain](https://js.langchain.com/docs/integrations/text_embedding/cloudflare_ai/) to build Retrieval-Augmented Generation (RAG) applications using [Workers AI](/workers-ai/) and [Vectorize](/vectorize/). - -Give your agents more context and the ability to search across content, reply to user queries, and expand their domain knowledge. - -```sh -npm i @langchain/cloudflare hono -``` - -```ts collapse={30-1000} -import { - CloudflareVectorizeStore, - CloudflareWorkersAIEmbeddings -} from "@langchain/cloudflare"; -import { VectorizeIndex } from "@cloudflare/workers-types"; -import { Ai } from "@cloudflare/ai"; -import { Hono } from "hono"; - -export interface Env { - VECTORIZE_INDEX: VectorizeIndex; - AI: Ai; -} - -const app = new Hono<{ Bindings: Env }>(); - -app.get("/", async (c) => { - const embeddings = new CloudflareWorkersAIEmbeddings({ - binding: c.env.AI, - model: "@cf/baai/bge-small-en-v1.5", - }); - - const store = new CloudflareVectorizeStore(embeddings, { - index: c.env.VECTORIZE_INDEX, - }); - - const results = await store.similaritySearch("hello", 5); - return c.json(results); -}); - -app.post("/load", async (c) => { - const embeddings = new CloudflareWorkersAIEmbeddings({ - binding: c.env.AI, - model: "@cf/baai/bge-small-en-v1.5", - }); - - const store = new CloudflareVectorizeStore(embeddings, { - index: c.env.VECTORIZE_INDEX, - }); - - const documents = [ - { pageContent: "hello", metadata: {} }, - { pageContent: "world", metadata: {} }, - { pageContent: "hi", metadata: {} } - ]; - - await store.addDocuments(documents, { - ids: ["id1", "id2", "id3"] - }); - - return c.json({ success: true }); -}); - -app.delete("/clear", async (c) => { - const embeddings = new CloudflareWorkersAIEmbeddings({ - binding: c.env.AI, - model: "@cf/baai/bge-small-en-v1.5", - }); - - const store = new CloudflareVectorizeStore(embeddings, { - index: c.env.VECTORIZE_INDEX, - }); - - await store.delete({ ids: ["id1", "id2", "id3"] }); - return c.json({ success: true }); -}); - -export default app; -``` - - - - -Ship faster with the [AI SDK](https://sdk.vercel.ai/docs/introduction): make it easier to generate text, tool call and/or get structured output from your AI models (and then deploy it to [Workers](/workers/)). - -```sh -npm i ai workers-ai-provider -``` - -```ts collapse={30-1000} -import { createWorkersAI } from 'workers-ai-provider'; -import { streamText } from 'ai'; - -type Env = { - AI: Ai; -}; - -export default { - async fetch(_: Request, env: Env) { - const workersai = createWorkersAI({ binding: env.AI }); - const result = streamText({ - model: workersai('@cf/meta/llama-3.2-3b-instruct'), - prompt: 'Write short essay on why you like Cloudflare Durable Objects.', - }); - - return result.toTextStreamResponse({ - headers: { - 'Content-Type': 'text/x-unknown', - 'content-encoding': 'identity', - 'transfer-encoding': 'chunked', - }, - }); - }, -}; -``` - - - - -Use any model provider with OpenAI compatible endpoints, including [ChatGPT](https://platform.openai.com/docs/quickstart), [DeepSeek](https://api-docs.deepseek.com/) and [Workers AI](/workers-ai/configuration/open-ai-compatibility/), directly from Cloudflare Workers. - -```sh -npm i openai -``` - -```ts collapse={30-1000} -import OpenAI from "openai"; - -export interface Env { - OPENAI_API_KEY: string; -} - -export default { - async fetch(request: Request, env: Env) { - const url = new URL(request.url); - const prompt = url.searchParams.get('prompt') || "Make some robot noises"; - - const openai = new OpenAI({ - apiKey: env.OPENAI_API_KEY - }); - - const chatCompletion = await openai.chat.completions.create({ - messages: [{ role: "user", content: prompt }], - model: "gpt-3.5-turbo", - }); - - const embeddings = await openai.embeddings.create({ - model: "text-embedding-ada-002", - input: "Cloudflare Agents documentation", - }); +Head to the [getting started tutorial](/agents/getting-started/writing-your-first-agent/) to dive into shipping your first Agent on Cloudflare. - return new Response(JSON.stringify({ chatCompletion, embeddings })); - } -} -``` - - +### What's next? +- [Real-time & websockets](/examples/websockets) +- [Manage & sync state](/manage-and-sync-state) +- [Using AI Models](/using-ai-models) *** -## All the products you need in one platform +### Build on the Cloudflare Platform From 68928f65e15eb825ae56ce68893f4c324e6512bd Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 14:45:37 -0500 Subject: [PATCH 20/41] ai models --- .../docs/agents/examples/using-ai-models.mdx | 161 ++++++++++++++++-- 1 file changed, 151 insertions(+), 10 deletions(-) diff --git a/src/content/docs/agents/examples/using-ai-models.mdx b/src/content/docs/agents/examples/using-ai-models.mdx index cfd85b2e536700a..b1fb2de9f52a4cd 100644 --- a/src/content/docs/agents/examples/using-ai-models.mdx +++ b/src/content/docs/agents/examples/using-ai-models.mdx @@ -8,7 +8,7 @@ sidebar: import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -Agents can communicate with AI models hosted on any provider, including [Workers AI](/workers-ai/), OpenAI, Anthropic, and Google's Gemini. +Agents can communicate with AI models hosted on any provider, including [Workers AI](/workers-ai/), OpenAI, Anthropic, and Google's Gemini, and use the model routing features in [AI Gateway](/ai-gateway/) to route across providers, eval responses, and manage AI provider rate limits. Because Agents are built on top of [Durable Objects](/durable-objects/), each Agent or chat session is associated with a stateful compute instance. Tradtional serverless architectures often present challenges for persistent connections needed in real-time applications like chat. @@ -18,16 +18,116 @@ A user can disconnect during a long-running response from a modern reasoning mod ### Workers AI -TODO +### Inference endpoints -- Workers AI -- AI Gateway / model routing +You can use [any of the models available in Workers AI](/workers-ai/models/) within your Agent by [configuring a binding](/workers-ai/configuration/bindings/). +Workers AI supports streaming responses out-of-the-box by setting `stream: true`, and we strongly recommend using them to avoid buffering and delaying responses, especially for larger models or reasoning models that require more time to generate a response. + + + +```ts +import { Agent } from "@cloudflare/agents" + +interface Env { + AI: Ai; +} + +export class MyAgent extends Agent { + async onRequest(request: Request) { + const response = await env.AI.run( + "@cf/deepseek-ai/deepseek-r1-distill-qwen-32b", + { + prompt: "Build me a Cloudflare Worker that returns JSON.", + stream: true, // Stream a response and don't block the client! + } + ); + + // Return the stream + return new Response(answer, { + headers: { "content-type": "text/event-stream" } + } +} +``` + + + +Your wrangler configuration will need an `ai` binding added: + + + +```toml +[ai] +binding = "AI" +``` + + + + +### Model routing + +You can also use the model routing features in [AI Gateway](/ai-gateway/) directly from an Agent by specifying a [`gateway` configuration](/ai-gateway/providers/workersai/) when calling the AI binding. + +:::note + +Model routing allows you to route requests to different AI models based on whether they are reachable, rate-limiting your client, and/or if you've exceeded your cost budget for a specific provider. + +::: + + + +```ts +import { Agent } from "@cloudflare/agents" + +interface Env { + AI: Ai; +} + +export class MyAgent extends Agent { + async onRequest(request: Request) { + const response = await env.AI.run( + "@cf/deepseek-ai/deepseek-r1-distill-qwen-32b", + { + prompt: "Build me a Cloudflare Worker that returns JSON." + }, + { + gateway: { + id: "{gateway_id}", // Specify your AI Gateway ID here + skipCache: false, + cacheTtl: 3360, + }, + }, + ); + + return Response.json(response) + } +} +``` + + + +Your wrangler configuration will need an `ai` binding added. This is shared across both Workers AI and AI Gateway. + + +```toml +[ai] +binding = "AI" +``` + + + +Visit the [AI Gateway documentation](/ai-gateway/) to learn how to configure a gateway and retrieve a gateway ID. ### AI SDK The [AI SDK](https://sdk.vercel.ai/docs/introduction) provides a unified API for using AI models, including for text generation, tool calling, structured responses, image generation, and more. +To use the AI SDK, install the `ai` package and use it within your Agent. The example below shows how it use it to generate text on request, but you can use it from any method within your Agent, including WebSocket handlers, as part of a scheduled task, or even when the Agent is initialized. + +```sh +npm install ai @ai-sdk/openai +``` + ```ts @@ -36,10 +136,6 @@ import { generateText } from 'ai'; import { openai } from '@ai-sdk/openai'; export class MyAgent extends Agent { - constructor(state: DurableObjectState, env: Env) { - super(state, env); - } - async onRequest(request: Request): Promise { const { text } = await generateText({ model: openai("o3-mini"), @@ -55,7 +151,52 @@ export class MyAgent extends Agent { ### OpenAI SDK +Agents can call models across any service, including those that support the OpenAI API. For example, you can use the OpenAI SDK to use one of [Google's Gemini models](https://ai.google.dev/gemini-api/docs/openai#node.js) directly from your Agent. + +Agents can stream responses back over HTTP using Server Sent Events (SSE) from within an `onRequest` handler, or by using the native [WebSockets](/agents/examples/websockets/) API to responses back to a a client over a long running WebSocket. -## Long-running LLM calls + + +```ts +import { Agent } from "@cloudflare/agents" +import { OpenAI } from "openai" -TODO \ No newline at end of file +export class MyAgent extends Agent { + async onRequest(request: Request): Promise { + const openai = new OpenAI({ + apiKey: this.env.GEMINI_API_KEY, + baseURL: "https://generativelanguage.googleapis.com/v1beta/openai/" + }); + + // Create a TransformStream to handle streaming data + let { readable, writable } = new TransformStream(); + let writer = writable.getWriter(); + const textEncoder = new TextEncoder(); + + // Use ctx.waitUntil to run the async function in the background + // so that it doesn't block the streaming response + ctx.waitUntil( + (async () => { + const stream = await openai.chat.completions.create({ + model: "4o", + messages: [{ role: "user", content: "Write me a Cloudflare Worker." }], + stream: true, + }); + + // loop over the data as it is streamed and write to the writeable + for await (const part of stream) { + writer.write( + textEncoder.encode(part.choices[0]?.delta?.content || ""), + ); + } + writer.close(); + })(), + ); + + // Return the readable stream back to the client + return new Response(readable) + } +} +``` + + From 731d6bb44d45c49cac8d5dd7a400fffd4e14bbbd Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 15:57:13 -0500 Subject: [PATCH 21/41] guides, ai models --- .../docs/agents/examples/using-ai-models.mdx | 69 +++++++++++++++++-- .../docs/agents/examples/websockets.mdx | 2 +- .../getting-started/observing-agents.mdx | 19 ----- .../guides/anthropic-agent-patterns.mdx | 9 +++ .../docs/agents/guides/human-in-the-loop.mdx | 9 +++ 5 files changed, 83 insertions(+), 25 deletions(-) delete mode 100644 src/content/docs/agents/getting-started/observing-agents.mdx create mode 100644 src/content/docs/agents/guides/anthropic-agent-patterns.mdx create mode 100644 src/content/docs/agents/guides/human-in-the-loop.mdx diff --git a/src/content/docs/agents/examples/using-ai-models.mdx b/src/content/docs/agents/examples/using-ai-models.mdx index b1fb2de9f52a4cd..5c21d9d8d0110f7 100644 --- a/src/content/docs/agents/examples/using-ai-models.mdx +++ b/src/content/docs/agents/examples/using-ai-models.mdx @@ -6,7 +6,7 @@ sidebar: --- -import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; +import { AnchorHeading, MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; Agents can communicate with AI models hosted on any provider, including [Workers AI](/workers-ai/), OpenAI, Anthropic, and Google's Gemini, and use the model routing features in [AI Gateway](/ai-gateway/) to route across providers, eval responses, and manage AI provider rate limits. @@ -16,9 +16,69 @@ A user can disconnect during a long-running response from a modern reasoning mod ## Calling AI Models +You can call models from any method within an Agent, including from HTTP requests using the [`onRequest`](/agents/api-reference/sdk/) handler, when a [scheduled task](/agents/examples/schedule-tasks/) runs, when handling a WebSocket message in the [`onMessage`](/agents/examples/websockets/) handler, or from any of your own methods. + +Importantly, Agents can call AI models on their own — autonomously — and can handle long-running responses that can take minutes (or longer) to respond in full. + +### Long-running model requests {/*long-running-model-requests*/} + +Modern [reasoning models](https://platform.openai.com/docs/guides/reasoning) or "thinking" model can take some time to both generate a response _and_ stream the response back to the client. + +Instead of buffering the entire response, or risking the client disconecting, you can stream the response back to the client by using the [WebSocket API](/agents/examples/websockets/). + + + +```ts +import { Agent } from "@cloudflare/agents" +import { OpenAI } from "openai" + +export class MyAgent extends Agent { + async onConnect(connection: Connection, ctx: ConnectionContext) { + // Omitted for simplicity: authenticating the user + connection.accept() + } + + async onMessage(connection: Connection, message: WSMessage) { + let msg = JSON.parse(message) + // This can run as long as it needs to, and return as many messages as it needs to! + await queryReasoningModel(connection, msg.prompt) + } + + async queryReasoningModel(connection: Connection, userPrompt: string) { + const client = new OpenAI({ + apiKey: this.env.OPENAI_API_KEY, + }); + + try { + const stream = await client.chat.completions.create({ + model: this.env.MODEL || 'o3-mini', + messages: [{ role: 'user', content: userPrompt }], + stream: true, + }); + + // Stream responses back as WebSocket messages + for await (const chunk of stream) { + const content = chunk.choices[0]?.delta?.content || ''; + if (content) { + connection.send(JSON.stringify({ type: 'chunk', content })); + } + } + + // Send completion message + connection.send(JSON.stringify({ type: 'done' })); + } catch (error) { + connection.send(JSON.stringify({ type: 'error', error: error })); + } + } +``` + + + +You can also persist AI model responses back to [Agent's internal state](/agents/examples/manage-and-sync-state/) by using the `this.setState` method. For example, if you run a [scheduled task](/agents/examples/scheduling-tasks/), you can store the output of the task and read it later. Or, if a user disconnects, read the message history back and send it to the user when they reconnect. + ### Workers AI -### Inference endpoints +### Hosted models You can use [any of the models available in Workers AI](/workers-ai/models/) within your Agent by [configuring a binding](/workers-ai/configuration/bindings/). @@ -63,7 +123,6 @@ binding = "AI" - ### Model routing You can also use the model routing features in [AI Gateway](/ai-gateway/) directly from an Agent by specifying a [`gateway` configuration](/ai-gateway/providers/workersai/) when calling the AI binding. @@ -149,11 +208,11 @@ export class MyAgent extends Agent { -### OpenAI SDK +### OpenAI compatible endpoints Agents can call models across any service, including those that support the OpenAI API. For example, you can use the OpenAI SDK to use one of [Google's Gemini models](https://ai.google.dev/gemini-api/docs/openai#node.js) directly from your Agent. -Agents can stream responses back over HTTP using Server Sent Events (SSE) from within an `onRequest` handler, or by using the native [WebSockets](/agents/examples/websockets/) API to responses back to a a client over a long running WebSocket. +Agents can stream responses back over HTTP using Server Sent Events (SSE) from within an `onRequest` handler, or by using the native [WebSockets](/agents/examples/websockets/) API in your Agent to responses back to a client, which is especially useful for larger models that can take over 30+ seconds to reply. diff --git a/src/content/docs/agents/examples/websockets.mdx b/src/content/docs/agents/examples/websockets.mdx index 7780270fa50011d..662002971133b56 100644 --- a/src/content/docs/agents/examples/websockets.mdx +++ b/src/content/docs/agents/examples/websockets.mdx @@ -1,5 +1,5 @@ --- -title: Real-time and WebSockets +title: Using WebSockets pcx_content_type: concept sidebar: order: 2 diff --git a/src/content/docs/agents/getting-started/observing-agents.mdx b/src/content/docs/agents/getting-started/observing-agents.mdx deleted file mode 100644 index f13e8f43bac290b..000000000000000 --- a/src/content/docs/agents/getting-started/observing-agents.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Testing your Agent -updated: 2025-02-20 -sidebar: - order: 3 - ---- - -import { Render, PackageManagers, WranglerConfig } from "~/components" - -:::note - -New to building Agents and/or using Cloudflare Workers? This tutorial will guide you through the process of creating your first Agent and deploying it live. - -If you're familiar with Workers, you can head over to our [quick start guide](/agents/get-started/quick-start/) or review the [Agents API Reference](/agents/api/workers-api). - -::: - -TODO: testing \ No newline at end of file diff --git a/src/content/docs/agents/guides/anthropic-agent-patterns.mdx b/src/content/docs/agents/guides/anthropic-agent-patterns.mdx new file mode 100644 index 000000000000000..733b411bda5493e --- /dev/null +++ b/src/content/docs/agents/guides/anthropic-agent-patterns.mdx @@ -0,0 +1,9 @@ +--- +pcx_content_type: navigation +title: Build a Human-in-the-loop Agent +external_link: https://github.com/cloudflare/agents/tree/main/guides/human-in-the-loop +sidebar: + order: 2 +head: [] +description: Implement human-in-the-loop functionality using Cloudflare Agents, allowing AI agents to request human approval before executing certain actions +--- diff --git a/src/content/docs/agents/guides/human-in-the-loop.mdx b/src/content/docs/agents/guides/human-in-the-loop.mdx new file mode 100644 index 000000000000000..f8ff08554a457bd --- /dev/null +++ b/src/content/docs/agents/guides/human-in-the-loop.mdx @@ -0,0 +1,9 @@ +--- +pcx_content_type: navigation +title: Implement Effective Agent Patterns +external_link: https://github.com/cloudflare/agents/tree/main/guides/anthropic-patterns +sidebar: + order: 3 +head: [] +description: Implement common agent patterns using the `@cloudflare/agents` framework. +--- From 34667bc94d64cad3f4ac452e15951a795ba93ddb Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 16:00:54 -0500 Subject: [PATCH 22/41] d1 --- src/content/docs/agents/examples/manage-and-sync-state.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx index c20c47fb122d4b4..168ab117fd5e469 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -172,4 +172,4 @@ Learn more about the zero-latency SQL storage that powers both Agents and Durabl ::: -The SQL API exposed to an Agent is similar to the one [within Durable Objects](/durable-objects/api/sql-storage/): Durable Object SQL methods available on `this.ctx.storage.sql`. You can use the same SQL queries with the Agent's database, create tables, and query data, as you would with Durable Objects or D1, as the dialect is the same. +The SQL API exposed to an Agent is similar to the one [within Durable Objects](/durable-objects/api/sql-storage/): Durable Object SQL methods available on `this.ctx.storage.sql`. You can use the same SQL queries with the Agent's database, create tables, and query data, just as you would with Durable Objects or [D1](/d1/). \ No newline at end of file From 2747050ed93539b5f9d7f4b85907887d146e28d4 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 16:17:19 -0500 Subject: [PATCH 23/41] useAgent --- .../agents/examples/manage-and-sync-state.mdx | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx index 168ab117fd5e469..3b9e850e33f2024 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -92,18 +92,40 @@ export class MyAgent extends Agent { ### Synchronizing state -Clients can connect to an Agent and stay synchronized with its state using the React hooks provided as part of `@cloudflare/agents/react`: +Clients can connect to an Agent and stay synchronized with its state using the React hooks provided as part of `@cloudflare/agents/react`. + +A React application can call `useAgent` to connect to a named Agent over WebSockets at ```ts - - +import { useState } from "react"; +import { useAgent } from "@cloudflare/agents/react"; + +function StateInterface() { + const [state, setState] = useState({ counter: 0 }); + + const agent = useAgent({ + agent: "thinking-agent", + name: "my-agent", + onStateUpdate: (newState) => setState(newState), + }); + + const increment = () => { + agent.setState({ counter: state.counter + 1 }); + }; + + return ( +
+
Count: {state.counter}
+ +
+ ); +} ```
- The state synchronization system: * Automatically syncs the Agent's state to all connected clients From e8f3978e9ac235f2972b9ea6c65211bb2129b443 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 16:24:00 -0500 Subject: [PATCH 24/41] fix 'er up --- src/content/docs/agents/examples/schedule-tasks.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index bf742a4cb72bb1f..75a627aec55cbbb 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -99,8 +99,8 @@ let tasks = this.getSchedules({ timeRange: { start: new Date(Date.now()), end: new Date(Date.now() + 60 * 60 * 1000), - }, -); + } +}); ```
From 10364233caf8adbb2e8e222a783a920f65b6abb9 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 18:10:02 -0500 Subject: [PATCH 25/41] browse, fix syntax --- .../docs/agents/examples/browse-the-web.mdx | 32 +++++++++++++++++-- .../docs/agents/examples/using-ai-models.mdx | 1 + 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/examples/browse-the-web.mdx index a95cad4e3abb7cb..c62c98da068ae75 100644 --- a/src/content/docs/agents/examples/browse-the-web.mdx +++ b/src/content/docs/agents/examples/browse-the-web.mdx @@ -13,6 +13,8 @@ Agents can browse the web using the [Browser Rendering](/browser-rendering/) API The [Browser Rendering](/browser-rendering/) allows you to spin up headless browser instances, render web pages, and interact with websites through your Agent. +You can define a method that uses Puppeteer to pull the content of a web page, parse the DOM, and extract relevant information by calling the OpenAI model: + ```ts @@ -21,9 +23,33 @@ interface Env { } export class MyAgent extends Agent { - constructor(env: Env) { - super(env); - } + async browse(browserInstance: Fetcher, urls: string[]) { + for (const url of urls) { + const browser = await puppeteer.launch(browserInstance); + const page = await browser.newPage(); + await page.goto(url); + + await page.waitForSelector('body'); + const bodyContent = await page.$eval('body', (element) => element.innerHTML); + const client = new OpenAI({ + apiKey: this.env.OPENAI_API_KEY, + }); + + await client.chat.completions.create({ + model: this.env.MODEL || "4o", + messages: [ + { + role: 'user', + content: `Return a JSON object with the product names, prices and URLs with the following format: { "name": "Product Name", "price": "Price", "url": "URL" } from the website content below. ${bodyContent}`, + }, + ], + response_format: { + type: 'json_object', + }, + }); + + await browser.close(); + } } ``` diff --git a/src/content/docs/agents/examples/using-ai-models.mdx b/src/content/docs/agents/examples/using-ai-models.mdx index 5c21d9d8d0110f7..f9d989d0aad12ee 100644 --- a/src/content/docs/agents/examples/using-ai-models.mdx +++ b/src/content/docs/agents/examples/using-ai-models.mdx @@ -70,6 +70,7 @@ export class MyAgent extends Agent { connection.send(JSON.stringify({ type: 'error', error: error })); } } +} ``` From fbe1d28b7636deec23d56d059efea65501caf482 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 18:40:54 -0500 Subject: [PATCH 26/41] testing --- src/content/docs/agents/api-reference/sdk.mdx | 2 +- .../getting-started/testing-your-agent.mdx | 135 +++++++++++++++++- .../writing-your-first-agent.mdx | 2 +- 3 files changed, 136 insertions(+), 3 deletions(-) diff --git a/src/content/docs/agents/api-reference/sdk.mdx b/src/content/docs/agents/api-reference/sdk.mdx index 8be66c7c0e88781..dd9ad0e23b32130 100644 --- a/src/content/docs/agents/api-reference/sdk.mdx +++ b/src/content/docs/agents/api-reference/sdk.mdx @@ -112,7 +112,7 @@ Your own methods can access the Agent's environment variables and bindings on `t You can create and run an instance of an Agent directly from a Worker in one of three ways: -1. Using the `routeAgentRequest` helper: this will automatically map requests to an individual Agent based on the `/agents/:agent/:name` URL pattern. +1. Using the `routeAgentRequest` helper: this will automatically map requests to an individual Agent based on the `/agents/:agent/:name` URL pattern. The value of `:agent` will be the name of your Agent class converted to `kebab-case`, and the value of `:name` will be the name of the Agent instance you want to create or retrieve. 2. Calling `getAgentByName`, which will create a new Agent instance if none exists by that name, or retrieve a handle to an existing instance. 3. The [Durable Objects stub API](/durable-objects/api/id/), which provides a lower level API for creating and retrieving Agents. diff --git a/src/content/docs/agents/getting-started/testing-your-agent.mdx b/src/content/docs/agents/getting-started/testing-your-agent.mdx index 8048bc6fa2e06fb..4ce4c641171e86b 100644 --- a/src/content/docs/agents/getting-started/testing-your-agent.mdx +++ b/src/content/docs/agents/getting-started/testing-your-agent.mdx @@ -8,4 +8,137 @@ sidebar: import { Render, PackageManagers, WranglerConfig } from "~/components" -TODO \ No newline at end of file +Because Agents run on Cloudflare Workers and Durable Objects, they can be tested using the same tools and techniques as Workers and Durable Objects. + +## Writing and runnning tests + +### Setup + +:::note + +The `@cloudflare/agents-starter` template and new Cloudflare Workers projects already include the relevant `vitest` and `@cloudflare/vitest-pool-workers` packages, as well as a valid `vitest.config.js` file. + +::: + +Before you write your first test, install the necessary packages: + +```sh +npm install vitest@2.1.8 --save-dev --save-exact +npm install @cloudflare/vitest-pool-workers --save-dev +``` + +Ensure that your `vitest.config.js` file is identical to the following: + +```js +import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config"; + +export default defineWorkersConfig({ + test: { + poolOptions: { + workers: { + wrangler: { configPath: "./wrangler.toml" }, + }, + }, + }, +}); +``` + +### Add the Agent configuration + +Add a `durableObjects` configuration to `vitest.config.js` with the name of your Agent class: + +```js +import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'; + +export default defineWorkersConfig({ + test: { + poolOptions: { + workers: { + main: './src/index.ts', + miniflare: { + durableObjects: { + NAME: 'MyAgent', + }, + }, + }, + }, + }, +}); +``` + +### Write a test + +:::note + +Review the [Vitest documentation](https://vitest.dev/) for more information on testing, including the test API reference and advanced testing techniques. + +::: + +Tests use the `vitest` framework. A basic test suite for your Agent can validate how your Agent responds to requests, but can also unit test your Agent's methods and state. + +```ts +import { env, createExecutionContext, waitOnExecutionContext, SELF } from 'cloudflare:test'; +import { describe, it, expect } from 'vitest'; +import worker from '../src'; +import { Env } from '../src'; + +interface ProvidedEnv extends Env {} + +describe('make a request to my Agent', () => { + // Unit testing approach + it('responds with state', async () => { + // Provide a valid URL that your Worker can use to route to your Agent + // If you are using routeAgentRequest, this will be /agent/:agent/:name + const request = new Request('http://example.com/agent/my-agent/agent-123'); + const ctx = createExecutionContext(); + const response = await worker.fetch(request, env, ctx); + await waitOnExecutionContext(ctx); + expect(await response.text()).toMatchObject({ hello: 'from your agent' }); + }); + + it('also responds with state', async () => { + const request = new Request('http://example.com/agent/my-agent/agent-123'); + const response = await SELF.fetch(request); + expect(await response.text()).toMatchObject({ hello: 'from your agent' }); + }); +}); +``` + +### Run tests + +Running tests is done using the `vitest` CLI: + +```sh +$ npm run test +# or run vitest directly +$ npx vitest +``` +```sh output + MyAgent + ✓ should return a greeting (1 ms) + +Test Files 1 passed (1) +``` + +Review the [documentation on testing](/workers/testing/vitest-integration/get-started/write-your-first-test/) for additional examples and test configuration. + +## Running Agents locally + +You can also run an Agent locally using the `wrangler` CLI: + +```sh +$ npx wrangler dev +``` +```sh output +Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development. + +Your worker has access to the following bindings: +- Durable Objects: + - MyAgent: MyAgent + Starting local server... +[wrangler:inf] Ready on http://localhost:53645 +``` + +This spins up a local development server that runs the same runtime as Cloudflare Workers, and allows you to iterate on your Agent's code and test it locally without deploying it. + +Visit the [`wrangler dev`](https://developers.cloudflare.com/workers/wrangler/commands/#dev) docs to review the CLI flags and configuration options. diff --git a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx index ada15d704c8fcd9..f15b2129ab6048f 100644 --- a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx +++ b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx @@ -6,7 +6,7 @@ sidebar: --- -import { Render, PackageManagers, WranglerConfig } from "~/components" +import { Render, PackageManagers, TypeScriptExample, WranglerConfig } from "~/components" :::note From 4c835c9fa22a249be9e4c398064145072230c44d Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 18:56:34 -0500 Subject: [PATCH 27/41] fix --- src/content/docs/agents/examples/browse-the-web.mdx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/examples/browse-the-web.mdx index c62c98da068ae75..a8dc7bde779e5a6 100644 --- a/src/content/docs/agents/examples/browse-the-web.mdx +++ b/src/content/docs/agents/examples/browse-the-web.mdx @@ -24,6 +24,7 @@ interface Env { export class MyAgent extends Agent { async browse(browserInstance: Fetcher, urls: string[]) { + let responses = []; for (const url of urls) { const browser = await puppeteer.launch(browserInstance); const page = await browser.newPage(); @@ -35,8 +36,8 @@ export class MyAgent extends Agent { apiKey: this.env.OPENAI_API_KEY, }); - await client.chat.completions.create({ - model: this.env.MODEL || "4o", + let resp = await client.chat.completions.create({ + model: this.env.MODEL, messages: [ { role: 'user', @@ -48,8 +49,12 @@ export class MyAgent extends Agent { }, }); + responses.push(resp); await browser.close(); } + + return responses; + } } ``` From ba111853943dc7acc95a1dcfb44fe9894a319b0e Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 19:01:46 -0500 Subject: [PATCH 28/41] fix --- src/content/docs/agents/examples/evals.mdx | 11 ----------- src/content/docs/agents/examples/self-host.mdx | 11 ----------- src/content/docs/agents/examples/using-ai-models.mdx | 1 + 3 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 src/content/docs/agents/examples/evals.mdx delete mode 100644 src/content/docs/agents/examples/self-host.mdx diff --git a/src/content/docs/agents/examples/evals.mdx b/src/content/docs/agents/examples/evals.mdx deleted file mode 100644 index b6d7d27c727e7d2..000000000000000 --- a/src/content/docs/agents/examples/evals.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Evals -pcx_content_type: concept -sidebar: - order: 15 - ---- - -import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; - -TODO diff --git a/src/content/docs/agents/examples/self-host.mdx b/src/content/docs/agents/examples/self-host.mdx deleted file mode 100644 index 760509c3a6ca454..000000000000000 --- a/src/content/docs/agents/examples/self-host.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Self-hosting Agents -pcx_content_type: concept -sidebar: - order: 100 - ---- - -import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; - -TODO diff --git a/src/content/docs/agents/examples/using-ai-models.mdx b/src/content/docs/agents/examples/using-ai-models.mdx index f9d989d0aad12ee..36948f116ba88cb 100644 --- a/src/content/docs/agents/examples/using-ai-models.mdx +++ b/src/content/docs/agents/examples/using-ai-models.mdx @@ -107,6 +107,7 @@ export class MyAgent extends Agent { // Return the stream return new Response(answer, { headers: { "content-type": "text/event-stream" } + }) } } ``` From c90c75ce0bec53cb08c384bae958c6da7555aa77 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 20:14:30 -0500 Subject: [PATCH 29/41] workflows --- .../docs/agents/examples/run-workflows.mdx | 89 +++++++++++-------- .../agents/getting-started/quick-start.mdx | 45 +++++----- .../writing-your-first-agent.mdx | 12 ++- 3 files changed, 87 insertions(+), 59 deletions(-) diff --git a/src/content/docs/agents/examples/run-workflows.mdx b/src/content/docs/agents/examples/run-workflows.mdx index 4cc72f7482e6aef..142aef1e99b9227 100644 --- a/src/content/docs/agents/examples/run-workflows.mdx +++ b/src/content/docs/agents/examples/run-workflows.mdx @@ -8,57 +8,79 @@ sidebar: import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -TODO - show how to invoke a Workflow from an Agent - Agents can trigger asynchronous [Workflows](/workflows/), allowing your Agent to run complex, multi-step tasks in the background. This can include post-processing files that a user has uploaded, updating the embeddings in a [vector database](/vectorize/), and/or managing long-running user-lifecycle email or SMS notification workflows. Because an Agent is just like a Worker script, it can create Workflows defined in the same project (script) as the Agent _or_ in a different project. +:::note[Agents vs. Workflows] + +Agents and Workflows have some similarities: they can both run tasks asynchronously. For straightforward tasks that are linear or need to run to completion, a Workflow can be ideal: steps can be retried, they can be cancelled, and can act on events. + +Agents do not have to run to completion: they can loop, branch and run forever, and they can also interact directly with users (over HTTP or WebSockets). An Agent can be used to trigger multiple Workflows as it runs, and can thus be used to co-ordinate and manage Workflows to achieve its goals. + +::: + ## Trigger a Workflow +An Agent can trigger one or more Workflows from within any method, whether from an incoming HTTP request, a WebSocket connection, on a delay or schedule, and/or from any other action the Agent takes. + +Trigering a Workflow from an Agent is no different from [triggering a Workflow from a Worker script](/workflows/build/trigger-workflows/): + ```ts interface Env { - BROWSER: Fetcher; + MY_WORKFLOW: Workflow; + MyAgent: AgentNamespace; } export class MyAgent extends Agent { + async onRequest(request: Request) { + let userId = request.headers.get("user-id"); + // Trigger a schedule that runs a Workflow + // Pass it a payload + let { taskId } = await this.schedule(300, "runWorkflow", { id: userId, flight: "DL264", date: "2025-02-23" }); + } + + async runWorkflow(data) { + let instance = await env.MY_WORKFLOW.create({ + id: data.id, + params: data, + }) + + // Schedule another task that checks the Workflow status every 5 minutes... + await this.schedule("*/5 * * * *", "checkWorkflowStatus", { id: instance.id }); + } +} +export class MyWorkflow extends WorkflowEntrypoint { + async run(event: WorkflowEvent, step: WorkflowStep) { + // Your Workflow code here + } } ``` +You'll also need to make sure your Agent [has a binding to your Workflow](/workflows/build/trigger-workflows/#workers-api-bindings) so that it can call it: + ```jsonc { - "$schema": "node_modules/wrangler/config-schema.json", - "name": "agents-example", - "main": "src/index.ts", - "compatibility_date": "2025-02-23", - "compatibility_flags": ["nodejs_compat"], + // ... // Create a binding between your Agent and your Workflow - "workflows": [{ "name": "EMAIL_WORKFLOW", "class_name": "EmailWorkflow" }], - "durable_objects": { - "bindings": [ - { - "name": "MyAgent", - "class_name": "MyAgent", - }, - ], - }, - "migrations": [ + "workflows": [ { - "tag": "v1", - // Mandatory for the Agent to store state - "new_sqlite_classes": ["MyAgent"], - }, - ], - "observability": { - "enabled": true, - }, + // Required: + "name": "EMAIL_WORKFLOW", + "class_name": "MyWorkflow", + // Optional: set the script_name field if your Workflow is defined in a + // different project from your Agent + "script_name": "email-workflows" + } + ], + // ... } ``` @@ -72,15 +94,12 @@ You can also call a Workflow that is defined in a different Workers script from ```jsonc { - // ... - "workflows": [ - { "name": "EMAIL_WORKFLOW", - "class_name": "EmailWorkflow", - // Set script_name to the name of the Worker that contains the EmailWorkflow definition - "script_name": "email-workflow-prod" - }, - ], - // ... + // Required: + "name": "EMAIL_WORKFLOW", + "class_name": "MyWorkflow", + // Optional: set tthe script_name field if your Workflow is defined in a + // different project from your Agent + "script_name": "email-workflows" } ``` diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index 2910354b42c77ad..d0e1fac736d77ea 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -7,7 +7,7 @@ sidebar: --- -import { Render, PackageManagers, TypeScriptExample, WranglerConfig } from "~/components" +import { Render, FileTree, PackageManagers, TypeScriptExample, WranglerConfig } from "~/components" :::note @@ -17,27 +17,31 @@ If you're new to Cloudflare Workers, Agents, or Cloudflare in general, we recomm ::: -TODO: quick start - -1. Use the template to create a new project -2. Open `src/index.ts` -3. Get familiar with it -4. Add some functionality (example) -5. Deploy it. - ## Prerequisites -## 1. Create an Agents project +## 1. Create a new Agent +You can get started by using the `cloudflare/agents-starter` template to create a new project: +This will create a new directory called `my-agent` with a number of files, but there are three we need to focus on: + + +- src + - **index.ts** **where your Agent's code is defined** +- **wrangler.jsonc** project configuration +- test + - index.spec.ts test definitions +- ... + + TODO: - what this template does @@ -56,17 +60,6 @@ Open up `src/index.ts` in your favorite text editor: import { Agent } from "@cloudflare/agents"; export class MyAgent extends Agent { - async onRequest(request) { - // Code that your Agent runs on a request - }, - - - async schedule(when, callback, payload) { - // Code that your Agent runs on a schedule - }, - - - } ``` @@ -90,4 +83,10 @@ TODO ## 5. Build out your Agent -TODO +OK, so you have an Agent deployed and running. What's next? + +- Understand more about the [Agent framework API](/agents/api-reference/sdk/) +- [Call AI models](/agents/examples/using-ai-models/) from your Agent +- Learn how to [persist state to and query data stored in](/agents/examples/manage-and-sync-state/) your Agent +- Run [scheduled tasks](/agents/examples/schedule-tasks/) +- Trigger [asynchronous workflows](/agents/examples/run-workflows/) that your Agent can co-ordinate and manage diff --git a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx index f15b2129ab6048f..26be30bb7ee09c5 100644 --- a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx +++ b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx @@ -16,4 +16,14 @@ If you're familiar with Workers, you can head over to our [quick start guide](/a ::: -TODO: full beginner tutorial \ No newline at end of file +## Prerequisites + + + +## 1. Create an Agents project + + From ae05a2ec0a61c9273f06c2a130974099a351e1e1 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 20:21:47 -0500 Subject: [PATCH 30/41] @cloudflare/agents -> agents-sdk --- src/content/docs/agents/api-reference/sdk.mdx | 14 +++++++------- .../docs/agents/examples/manage-and-sync-state.mdx | 8 ++++---- .../docs/agents/examples/schedule-tasks.mdx | 2 +- .../docs/agents/examples/using-ai-models.mdx | 10 +++++----- src/content/docs/agents/examples/websockets.mdx | 12 ++++++------ .../docs/agents/getting-started/quick-start.mdx | 2 +- .../agents/getting-started/testing-your-agent.mdx | 2 +- .../docs/agents/guides/human-in-the-loop.mdx | 2 +- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/content/docs/agents/api-reference/sdk.mdx b/src/content/docs/agents/api-reference/sdk.mdx index dd9ad0e23b32130..258a4d5c0753a2b 100644 --- a/src/content/docs/agents/api-reference/sdk.mdx +++ b/src/content/docs/agents/api-reference/sdk.mdx @@ -8,12 +8,12 @@ sidebar: import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -At its most basic, an Agent is a JavaScript class that extends the `Agent` class from the `@cloudflare/agents` package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. +At its most basic, an Agent is a JavaScript class that extends the `Agent` class from the `agents-sdk` package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. ```ts -import { Agent } from "@cloudflare/agents"; +import { Agent } from "agents-sdk"; class MyAgent extends Agent { // Define methods on the Agent @@ -30,14 +30,14 @@ Instances of an Agent are addressed by a unique identifier: that identifier (ID) ## The Agent class -Writing an Agent requires you to define a class that extends the `Agent` class from the `@cloudflare/agents` package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. +Writing an Agent requires you to define a class that extends the `Agent` class from the `agents-sdk` package. An Agent encapsulates all of the logic for an Agent, including how clients can connect to it, how it stores state, the methods it exposes, and any error handling. An Agent has the following class methods: ```ts -import { Agent } from "@cloudflare/agents"; +import { Agent } from "agents-sdk"; interface Env { // Define environment variables & bindings here @@ -87,7 +87,7 @@ class MyAgent extends Agent { } // Called when the Agent's state is updated - // via this.setState or the useAgent hook from the @cloudflare/agents/react package. + // via this.setState or the useAgent hook from the agents-sdk/react package. async onStateUpdate(state: any) { // 'state' will be typed if you supply a type parameter to the Agent class. } @@ -121,7 +121,7 @@ These three patterns are shown below: we recommend using either `routeAgentReque ```ts -import { Agent, AgentNamespace, getAgentByName, routeAgentRequest } from '@cloudflare/agents'; +import { Agent, AgentNamespace, getAgentByName, routeAgentRequest } from 'agents-sdk'; interface Env { // Define your Agent on the environment here @@ -134,7 +134,7 @@ export default { async fetch(request, env, ctx): Promise { // Routed addressing // Automatically routes HTTP requests and/or WebSocket connections to /agents/:agent/:name - // Best for: connecting React apps directly to Agents using useAgent from @cloudflare/agents/react + // Best for: connecting React apps directly to Agents using useAgent from agents-sdk/react (await routeAgentRequest(request, env)) || Response.json({ msg: 'no agent here' }, { status: 404 }); // Named addressing diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx index 3b9e850e33f2024..4b5b95ec1b323c4 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -23,7 +23,7 @@ Every Agent has built-in state management capabilities. You can set and update t ```ts -import { Agent } from "@cloudflare/agents"; +import { Agent } from "agents-sdk"; export class MyAgent extends Agent { // Update state in response to events @@ -58,7 +58,7 @@ If you're using TypeScript, you can also provide a type for your Agent's state b ```ts -import { Agent } from "@cloudflare/agents"; +import { Agent } from "agents-sdk"; interface Env {} @@ -92,7 +92,7 @@ export class MyAgent extends Agent { ### Synchronizing state -Clients can connect to an Agent and stay synchronized with its state using the React hooks provided as part of `@cloudflare/agents/react`. +Clients can connect to an Agent and stay synchronized with its state using the React hooks provided as part of `agents-sdk/react`. A React application can call `useAgent` to connect to a named Agent over WebSockets at @@ -100,7 +100,7 @@ A React application can call `useAgent` to connect to a named Agent over WebSock ```ts import { useState } from "react"; -import { useAgent } from "@cloudflare/agents/react"; +import { useAgent } from "agents-sdk/react"; function StateInterface() { const [state, setState] = useState({ counter: 0 }); diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index 75a627aec55cbbb..0849c06fdc7eb23 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -18,7 +18,7 @@ You can call `this.schedule` within any method on an Agent, and schedule tens-of ```ts -import { Agent } from "@cloudflare/agents" +import { Agent } from "agents-sdk" export class SchedulingAgent extends Agent { async onRequest(request) { diff --git a/src/content/docs/agents/examples/using-ai-models.mdx b/src/content/docs/agents/examples/using-ai-models.mdx index 36948f116ba88cb..3808c0579234049 100644 --- a/src/content/docs/agents/examples/using-ai-models.mdx +++ b/src/content/docs/agents/examples/using-ai-models.mdx @@ -29,7 +29,7 @@ Instead of buffering the entire response, or risking the client disconecting, yo ```ts -import { Agent } from "@cloudflare/agents" +import { Agent } from "agents-sdk" import { OpenAI } from "openai" export class MyAgent extends Agent { @@ -88,7 +88,7 @@ Workers AI supports streaming responses out-of-the-box by setting `stream: true` ```ts -import { Agent } from "@cloudflare/agents" +import { Agent } from "agents-sdk" interface Env { AI: Ai; @@ -138,7 +138,7 @@ Model routing allows you to route requests to different AI models based on wheth ```ts -import { Agent } from "@cloudflare/agents" +import { Agent } from "agents-sdk" interface Env { AI: Ai; @@ -192,7 +192,7 @@ npm install ai @ai-sdk/openai ```ts -import { Agent } from "@cloudflare/agents" +import { Agent } from "agents-sdk" import { generateText } from 'ai'; import { openai } from '@ai-sdk/openai'; @@ -219,7 +219,7 @@ Agents can stream responses back over HTTP using Server Sent Events (SSE) from w ```ts -import { Agent } from "@cloudflare/agents" +import { Agent } from "agents-sdk" import { OpenAI } from "openai" export class MyAgent extends Agent { diff --git a/src/content/docs/agents/examples/websockets.mdx b/src/content/docs/agents/examples/websockets.mdx index 662002971133b56..8eccb861b04b4eb 100644 --- a/src/content/docs/agents/examples/websockets.mdx +++ b/src/content/docs/agents/examples/websockets.mdx @@ -20,7 +20,7 @@ Here's an example of an Agent that echoes back any message it receives: ```ts -import { Agent, Connection } from "@cloudflare/agents"; +import { Agent, Connection } from "agents-sdk"; export class ChatAgent extends Agent { async onConnect(connection: Connection, ctx: ConnectionContext) { @@ -55,12 +55,12 @@ export class ChatAgent extends Agent { ## Connecting clients -The Agent framework includes a useful helper package for connecting directly to your Agent (or other Agents) from a client application. Import `@cloudflare/agents/client`, create an instance of `AgentClient` and use it to connect to an instance of your Agent: +The Agent framework includes a useful helper package for connecting directly to your Agent (or other Agents) from a client application. Import `agents-sdk/client`, create an instance of `AgentClient` and use it to connect to an instance of your Agent: ```ts -import { AgentClient } from "@cloudflare/agents/client"; +import { AgentClient } from "agents-sdk/client"; const connection = new AgentClient({ agent: "dialogue-agent", @@ -83,12 +83,12 @@ connection.send( ## React clients -React-based applications can import `@cloudflare/agents/react` and use the `useAgent` hook to connect to an instance of an Agent directly: +React-based applications can import `agents-sdk/react` and use the `useAgent` hook to connect to an instance of an Agent directly: ```ts -import { useAgent } from "@cloudflare/agents/react"; +import { useAgent } from "agents-sdk/react"; function AgentInterface() { const connection = useAgent({ @@ -129,7 +129,7 @@ Define `onError` and `onClose` methods on your Agent to explicitly handle WebSoc ```ts -import { Agent, Connection } from "@cloudflare/agents"; +import { Agent, Connection } from "agents-sdk"; export class ChatAgent extends Agent { // onConnect and onMessage methods diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index d0e1fac736d77ea..1db52d8fa00733c 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -57,7 +57,7 @@ Open up `src/index.ts` in your favorite text editor: ```ts -import { Agent } from "@cloudflare/agents"; +import { Agent } from "agents-sdk"; export class MyAgent extends Agent { diff --git a/src/content/docs/agents/getting-started/testing-your-agent.mdx b/src/content/docs/agents/getting-started/testing-your-agent.mdx index 4ce4c641171e86b..74c6389de8f4f38 100644 --- a/src/content/docs/agents/getting-started/testing-your-agent.mdx +++ b/src/content/docs/agents/getting-started/testing-your-agent.mdx @@ -16,7 +16,7 @@ Because Agents run on Cloudflare Workers and Durable Objects, they can be tested :::note -The `@cloudflare/agents-starter` template and new Cloudflare Workers projects already include the relevant `vitest` and `@cloudflare/vitest-pool-workers` packages, as well as a valid `vitest.config.js` file. +The `agents-sdk-starter` template and new Cloudflare Workers projects already include the relevant `vitest` and `@cloudflare/vitest-pool-workers` packages, as well as a valid `vitest.config.js` file. ::: diff --git a/src/content/docs/agents/guides/human-in-the-loop.mdx b/src/content/docs/agents/guides/human-in-the-loop.mdx index f8ff08554a457bd..20b69c099ab7b85 100644 --- a/src/content/docs/agents/guides/human-in-the-loop.mdx +++ b/src/content/docs/agents/guides/human-in-the-loop.mdx @@ -5,5 +5,5 @@ external_link: https://github.com/cloudflare/agents/tree/main/guides/anthropic-p sidebar: order: 3 head: [] -description: Implement common agent patterns using the `@cloudflare/agents` framework. +description: Implement common agent patterns using the `agents-sdk` framework. --- From 6aa1260cbea19926d96fb2181807a9ee039f4838 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 20:38:23 -0500 Subject: [PATCH 31/41] fix links --- .../agents/2025-02-14-example-ai-prompts.mdx | 2 +- src/content/docs/agents/examples/schedule-tasks.mdx | 2 +- src/content/docs/agents/examples/using-ai-models.mdx | 2 +- .../docs/agents/getting-started/quick-start.mdx | 2 +- .../getting-started/writing-your-first-agent.mdx | 2 +- src/content/docs/agents/index.mdx | 12 ++++++------ 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/content/changelog/agents/2025-02-14-example-ai-prompts.mdx b/src/content/changelog/agents/2025-02-14-example-ai-prompts.mdx index c5071f049a2a5b2..b979df67b5b02d0 100644 --- a/src/content/changelog/agents/2025-02-14-example-ai-prompts.mdx +++ b/src/content/changelog/agents/2025-02-14-example-ai-prompts.mdx @@ -8,7 +8,7 @@ products: date: 2025-02-14T19:00:00Z --- -We've added an [example prompt](/agents/build/prompts/) to help you get started with building AI agents and applications on Cloudflare [Workers](/workers/), including [Workflows](/workflows/), [Durable Objects](/durable-objects/), and [Workers KV](/kv/). +We've added an [example prompt](/workers/get-started/prompting/) to help you get started with building AI agents and applications on Cloudflare [Workers](/workers/), including [Workflows](/workflows/), [Durable Objects](/durable-objects/), and [Workers KV](/kv/). You can use this prompt with your favorite AI model, including Claude 3.5 Sonnet, OpenAI's o3-mini, Gemini 2.0 Flash, or Llama 3.3 on Workers AI. Models with large context windows will allow you to paste the prompt directly: provide your own prompt within the `` tags. diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index 0849c06fdc7eb23..cd4e9de03da8bc1 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -70,7 +70,7 @@ Calling `await this.schedule` returns a `Schedule`, which includes the task's ra :::note[Maximum scheduled tasks] -Each task is mapped to a row in the Agent's underlying [SQLite database](/sqlite-in-durable-objects/), which means that each task can be up to 2 MB in size. The maximum number of tasks must be `(task_size * tasks) + all_other_state < maximum_database_size` (currently 1GB per Agent). +Each task is mapped to a row in the Agent's underlying [SQLite database](/durable-objects/api/sql-storage/), which means that each task can be up to 2 MB in size. The maximum number of tasks must be `(task_size * tasks) + all_other_state < maximum_database_size` (currently 1GB per Agent). ::: diff --git a/src/content/docs/agents/examples/using-ai-models.mdx b/src/content/docs/agents/examples/using-ai-models.mdx index 3808c0579234049..a1a2d4223142f83 100644 --- a/src/content/docs/agents/examples/using-ai-models.mdx +++ b/src/content/docs/agents/examples/using-ai-models.mdx @@ -75,7 +75,7 @@ export class MyAgent extends Agent { -You can also persist AI model responses back to [Agent's internal state](/agents/examples/manage-and-sync-state/) by using the `this.setState` method. For example, if you run a [scheduled task](/agents/examples/scheduling-tasks/), you can store the output of the task and read it later. Or, if a user disconnects, read the message history back and send it to the user when they reconnect. +You can also persist AI model responses back to [Agent's internal state](/agents/examples/manage-and-sync-state/) by using the `this.setState` method. For example, if you run a [scheduled task](/agents/examples/schedule-tasks/), you can store the output of the task and read it later. Or, if a user disconnects, read the message history back and send it to the user when they reconnect. ### Workers AI diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index 1db52d8fa00733c..fea98f4310b8665 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -13,7 +13,7 @@ import { Render, FileTree, PackageManagers, TypeScriptExample, WranglerConfig } **This quick-start guide will get you deploying your first Agent on Cloudflare in less than 5 minutes.** -If you're new to Cloudflare Workers, Agents, or Cloudflare in general, we recommend following the more comprehensive [Agents tutorial](/agents/get-started/tutorial/), which takes you through the process step-by-step. +If you're new to Cloudflare Workers, Agents, or Cloudflare in general, we recommend following the more comprehensive [Agents tutorial](/agents/getting-started/writing-your-first-agent/), ihich takes you through the process step-by-step. ::: diff --git a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx index 26be30bb7ee09c5..7cd5ad62d14c58c 100644 --- a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx +++ b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx @@ -12,7 +12,7 @@ import { Render, PackageManagers, TypeScriptExample, WranglerConfig } from "~/co New to building Agents and/or using Cloudflare Workers? This tutorial will guide you through the process of creating your first Agent and deploying it live. -If you're familiar with Workers, you can head over to our [quick start guide](/agents/get-started/quick-start/) or review the [Agents API Reference](/agents/api/workers-api). +If you're familiar with Workers, you can head over to our [quick start guide](/agents/getting-started/quick-start/) or review the [Agents API Reference](/agents/api-reference/sdk). ::: diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index 040a93af60eb799..cfde6dff7e6156a 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -23,11 +23,11 @@ import { Tabs, } from "~/components"; -Build and deploy AI-powered [agents](~/concepts/agents/) that can autonomously perform tasks, persist state, browse the web, query data and communicate back to users in real-time over any channel. +Build and deploy AI-powered [agents](/agents/) that can autonomously perform tasks, persist state, browse the web, query data and communicate back to users in real-time over any channel. ### Why builds agents on Cloudflare? -- **Batteries included**: Want your agent to search the web? Connect it to [Browser Rendering](/browser-rendering/). Store data? Write to the Agent's underlying [Durable Object](/workers/durable-objects/). Query your database? Connect it to your Postgres database [with Hyperdrive](/hyperdrive/). Stream data back in real-time to one, ten or one thousand users at once? Establish a [WebSocket](/workers/websockets/). Feed data to an AI model? Connect it to [Workers AI](/workers-ai/), OpenAI, Gemini, or Anthropic. +- **Batteries included**: Want your agent to search the web? Connect it to [Browser Rendering](/browser-rendering/). Store data? Write to the Agent's underlying [Durable Object](/durable-objects/). Query your database? Connect it to your Postgres database [with Hyperdrive](/hyperdrive/). Stream data back in real-time to one, ten or one thousand users at once? Establish a [WebSocket](/websockets/). Feed data to an AI model? Connect it to [Workers AI](/workers-ai/), OpenAI, Gemini, or Anthropic. - **Scale to production**: Deploy agents to Cloudflare's global network and let them scale out automatically. - **Don't break the bank**: Agents are built on Cloudflare Workers. Only pay when your agents are running. @@ -44,10 +44,10 @@ Use the agent started template to bootstrap your first agent: Head to the [getting started tutorial](/agents/getting-started/writing-your-first-agent/) to dive into shipping your first Agent on Cloudflare. -### What's next? -- [Real-time & websockets](/examples/websockets) -- [Manage & sync state](/manage-and-sync-state) -- [Using AI Models](/using-ai-models) +### What's next? +- [Real-time & websockets](/agents/examples/websockets) +- [Manage & sync state](/agents/examples/manage-and-sync-state) +- [Using AI Models](/agents/examples/using-ai-models) *** From 2001aa1dd6406f23f4eb47437616dbd11e625981 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 20:43:32 -0500 Subject: [PATCH 32/41] fix ordering + testing title --- .../docs/agents/examples/testing-your-agents.mdx | 11 ----------- .../docs/agents/getting-started/quick-start.mdx | 4 ++-- .../agents/getting-started/testing-your-agent.mdx | 7 ++++--- .../getting-started/writing-your-first-agent.mdx | 3 ++- 4 files changed, 8 insertions(+), 17 deletions(-) delete mode 100644 src/content/docs/agents/examples/testing-your-agents.mdx diff --git a/src/content/docs/agents/examples/testing-your-agents.mdx b/src/content/docs/agents/examples/testing-your-agents.mdx deleted file mode 100644 index 3533b30d810b06f..000000000000000 --- a/src/content/docs/agents/examples/testing-your-agents.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Testing Agents -pcx_content_type: concept -sidebar: - order: 11 - ---- - -import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; - -TODO diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index fea98f4310b8665..24902628e1ec5c3 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -1,9 +1,9 @@ --- title: Quick start pcx_content_type: get-started -updated: 2025-02-20 +updated: 2025-02-24 sidebar: - order: 10 + order: 2 --- diff --git a/src/content/docs/agents/getting-started/testing-your-agent.mdx b/src/content/docs/agents/getting-started/testing-your-agent.mdx index 74c6389de8f4f38..c3618d3b1a19624 100644 --- a/src/content/docs/agents/getting-started/testing-your-agent.mdx +++ b/src/content/docs/agents/getting-started/testing-your-agent.mdx @@ -1,8 +1,9 @@ --- -title: Observing Agents -updated: 2025-02-20 +title: Testing your Agents +pcx_content_type: get-started +updated: 2025-02-24 sidebar: - order: 2 + order: 10 --- diff --git a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx index 7cd5ad62d14c58c..522a146fe298275 100644 --- a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx +++ b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx @@ -1,6 +1,7 @@ --- title: Writing your first Agent -updated: 2025-02-20 +pcx_content_type: get-started +updated: 2025-02-24 sidebar: order: 1 From 196a5bac056e598f3f41f36014aa9db1e187e5c9 Mon Sep 17 00:00:00 2001 From: Rita Kozlov Date: Mon, 24 Feb 2025 20:47:15 -0500 Subject: [PATCH 33/41] update index --- src/content/docs/agents/index.mdx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index cfde6dff7e6156a..e2f91fcdc54739e 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -27,9 +27,20 @@ Build and deploy AI-powered [agents](/agents/) that can autonomously perform tas ### Why builds agents on Cloudflare? -- **Batteries included**: Want your agent to search the web? Connect it to [Browser Rendering](/browser-rendering/). Store data? Write to the Agent's underlying [Durable Object](/durable-objects/). Query your database? Connect it to your Postgres database [with Hyperdrive](/hyperdrive/). Stream data back in real-time to one, ten or one thousand users at once? Establish a [WebSocket](/websockets/). Feed data to an AI model? Connect it to [Workers AI](/workers-ai/), OpenAI, Gemini, or Anthropic. -- **Scale to production**: Deploy agents to Cloudflare's global network and let them scale out automatically. -- **Don't break the bank**: Agents are built on Cloudflare Workers. Only pay when your agents are running. +#### Cost-Effective +Pay only for [CPU usage](https://blog.cloudflare.com/workers-pricing-scale-to-zero/), not wall-clock time—ideal for agents with frequent pauses while awaiting LLM responses or external tools. + +#### Serverless AI Inference +Access AI models on-demand with [Workers AI](https://developers.cloudflare.com/workers-ai) without infrastructure management: +- Scalable inference infrastrcture on demand, without requiring pre-provisioning of GPU-powered VMs +- Pay-per-use billing +- Support for open-source and custom models + +#### Durable Execution +Built-in reliability for complex processes: +- State persistence across requests with Durable Objects +- Automatic retries through Workflows +- Context preservation during multi-step tasks ### Start building From 23c5fee5c7687882910b300570037a2c062302c4 Mon Sep 17 00:00:00 2001 From: Rita Kozlov Date: Mon, 24 Feb 2025 20:51:01 -0500 Subject: [PATCH 34/41] update index --- src/content/docs/agents/index.mdx | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index e2f91fcdc54739e..5b7f94915296746 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -27,20 +27,9 @@ Build and deploy AI-powered [agents](/agents/) that can autonomously perform tas ### Why builds agents on Cloudflare? -#### Cost-Effective -Pay only for [CPU usage](https://blog.cloudflare.com/workers-pricing-scale-to-zero/), not wall-clock time—ideal for agents with frequent pauses while awaiting LLM responses or external tools. - -#### Serverless AI Inference -Access AI models on-demand with [Workers AI](https://developers.cloudflare.com/workers-ai) without infrastructure management: -- Scalable inference infrastrcture on demand, without requiring pre-provisioning of GPU-powered VMs -- Pay-per-use billing -- Support for open-source and custom models - -#### Durable Execution -Built-in reliability for complex processes: -- State persistence across requests with Durable Objects -- Automatic retries through Workflows -- Context preservation during multi-step tasks +- **Cost-Effective**: Pay only for [CPU usage](https://blog.cloudflare.com/workers-pricing-scale-to-zero/), not wall-clock time—saving costs during agent pauses while awaiting LLM responses or external tools. +- Serverless AI Inference: Access AI models on-demand with [Workers AI](https://developers.cloudflare.com/workers-ai) with pay-per-use billing and no infrastructure management required. +- Durable Execution: Maintain state persistence and execution reliability for complex multi-step processes with built-in retry mechanisms, using [Durable Objects](https://developers.cloudflare.com/durable-objects) and [Workflows](https://developers.cloudflare.com/workflows). ### Start building From 4fc9c2fc398de7b178ab224a7e7fdcb4fa49b43e Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Mon, 24 Feb 2025 21:02:27 -0500 Subject: [PATCH 35/41] headers --- src/content/docs/agents/examples/manage-and-sync-state.mdx | 2 +- .../docs/agents/getting-started/testing-your-agent.mdx | 2 +- .../docs/agents/getting-started/writing-your-first-agent.mdx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content/docs/agents/examples/manage-and-sync-state.mdx b/src/content/docs/agents/examples/manage-and-sync-state.mdx index 4b5b95ec1b323c4..3262f5776f01a2b 100644 --- a/src/content/docs/agents/examples/manage-and-sync-state.mdx +++ b/src/content/docs/agents/examples/manage-and-sync-state.mdx @@ -16,7 +16,7 @@ Every Agent has built-in state management capabilities, including built-in stora Agent state is stored in SQL database that associate with each indidivual Agent instance: you can interact with it using the higher-level `this.setState` API (recommended) or by directly querying the database with `this.sql`. -### State API +#### State API Every Agent has built-in state management capabilities. You can set and update the Agent's state directly using `this.setState`: diff --git a/src/content/docs/agents/getting-started/testing-your-agent.mdx b/src/content/docs/agents/getting-started/testing-your-agent.mdx index c3618d3b1a19624..25e411047de7540 100644 --- a/src/content/docs/agents/getting-started/testing-your-agent.mdx +++ b/src/content/docs/agents/getting-started/testing-your-agent.mdx @@ -11,7 +11,7 @@ import { Render, PackageManagers, WranglerConfig } from "~/components" Because Agents run on Cloudflare Workers and Durable Objects, they can be tested using the same tools and techniques as Workers and Durable Objects. -## Writing and runnning tests +## Writing and running tests ### Setup diff --git a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx index 522a146fe298275..2cb8c9430b16ccc 100644 --- a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx +++ b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx @@ -17,11 +17,11 @@ If you're familiar with Workers, you can head over to our [quick start guide](/a ::: -## Prerequisites +### Prerequisites -## 1. Create an Agents project +### 1. Create an Agents project Date: Mon, 24 Feb 2025 21:08:24 -0500 Subject: [PATCH 36/41] remove updated --- src/content/docs/agents/getting-started/quick-start.mdx | 1 - src/content/docs/agents/getting-started/testing-your-agent.mdx | 1 - .../docs/agents/getting-started/writing-your-first-agent.mdx | 1 - 3 files changed, 3 deletions(-) diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index 24902628e1ec5c3..3fa36a6afe097c5 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -1,7 +1,6 @@ --- title: Quick start pcx_content_type: get-started -updated: 2025-02-24 sidebar: order: 2 diff --git a/src/content/docs/agents/getting-started/testing-your-agent.mdx b/src/content/docs/agents/getting-started/testing-your-agent.mdx index 25e411047de7540..d57f42948062a32 100644 --- a/src/content/docs/agents/getting-started/testing-your-agent.mdx +++ b/src/content/docs/agents/getting-started/testing-your-agent.mdx @@ -1,7 +1,6 @@ --- title: Testing your Agents pcx_content_type: get-started -updated: 2025-02-24 sidebar: order: 10 diff --git a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx index 2cb8c9430b16ccc..d25acb45ae82385 100644 --- a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx +++ b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx @@ -1,7 +1,6 @@ --- title: Writing your first Agent pcx_content_type: get-started -updated: 2025-02-24 sidebar: order: 1 From 73f6421a359d14a8d48e135ef7882f57bef8d165 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Tue, 25 Feb 2025 07:26:25 -0500 Subject: [PATCH 37/41] index.mdx --- .../agents/getting-started/quick-start.mdx | 16 ++---- src/content/docs/agents/index.mdx | 53 +++++++++++-------- .../agents/platform/agents-vs-workflows.mdx | 15 ------ 3 files changed, 34 insertions(+), 50 deletions(-) delete mode 100644 src/content/docs/agents/platform/agents-vs-workflows.mdx diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx index 3fa36a6afe097c5..de0506193fc9f98 100644 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ b/src/content/docs/agents/getting-started/quick-start.mdx @@ -27,28 +27,20 @@ You can get started by using the `cloudflare/agents-starter` template to create -This will create a new directory called `my-agent` with a number of files, but there are three we need to focus on: +This will create a new directory called `my-agent` with several files, including: +- **wrangler.jsonc** project configuration - src - **index.ts** **where your Agent's code is defined** -- **wrangler.jsonc** project configuration - test - - index.spec.ts test definitions + - index.spec.ts **where your tests are defined** - ... -TODO: - -- what this template does -- how to deploy it and get quick win -- how to iterate on it and extend it -- re-deploy -- go explore :-) - ## 2. Review the code Open up `src/index.ts` in your favorite text editor: diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index 5b7f94915296746..8a0cc11023d81e4 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -23,36 +23,49 @@ import { Tabs, } from "~/components"; -Build and deploy AI-powered [agents](/agents/) that can autonomously perform tasks, persist state, browse the web, query data and communicate back to users in real-time over any channel. +Build and deploy AI-powered Agents on Cloudflare that can autonomously perform tasks, communicate with clients in real time, persist state, execute long-running and repeat tasks on a schedule, send emails, run asynchronous workflows, browse the web, query data from your Postgres database, call AI models, support human-in-the-loop use-cases, and more. -### Why builds agents on Cloudflare? +#### Ship your first Agent -- **Cost-Effective**: Pay only for [CPU usage](https://blog.cloudflare.com/workers-pricing-scale-to-zero/), not wall-clock time—saving costs during agent pauses while awaiting LLM responses or external tools. -- Serverless AI Inference: Access AI models on-demand with [Workers AI](https://developers.cloudflare.com/workers-ai) with pay-per-use billing and no infrastructure management required. -- Durable Execution: Maintain state persistence and execution reliability for complex multi-step processes with built-in retry mechanisms, using [Durable Objects](https://developers.cloudflare.com/durable-objects) and [Workflows](https://developers.cloudflare.com/workflows). +Use the agent started template to create your first Agent: -### Start building +```sh +# install it +npm create cloudflare@latest -- --template=cloudflare/agents-starter +# and deploy it +npx wrangler@latest deploy +``` -Use the agent started template to bootstrap your first agent: +Head to the [getting started tutorial](/agents/getting-started/writing-your-first-agent/) to dive into shipping your first Agent on Cloudflare. - +If you're already building on [Workers](/workers/), you can install the `agents-sdk` package directly into an existing project: -Head to the [getting started tutorial](/agents/getting-started/writing-your-first-agent/) to dive into shipping your first Agent on Cloudflare. +```sh +npm i agents-sdk +``` + +Dive into the [Agent SDK reference](/agents/api-reference/sdk/) to learn more about how to use the `agents-sdk` package and defining an `Agent`. + +#### Why build agents on Cloudflare? +We built the `agents-sdk` with a few things in mind: -### What's next? -- [Real-time & websockets](/agents/examples/websockets) -- [Manage & sync state](/agents/examples/manage-and-sync-state) -- [Using AI Models](/agents/examples/using-ai-models) +- **Batteries (state) included**: Agents come with [built-in state management](/agents/examples/manage-and-sync-state/), with the ability to automatically sync state between an Agent and clients, trigger events on state changes, and read+write to each Agent's SQL database. +- **Communicative**: You can connect to an Agent via [WebSockets](/agents/examples/websockets/) and stream updates back to client in real-time. Handle a long-running response from a reasoning model, the results of an [asynchronous workflow](/agents/examples/asynchronous-workflows/), or build a chat app that builds on the `useAgent` hook included in the `agents-sdk`. +- **Extensible**: Agents are code. Use the [AI models](/agents/examples/using-ai-models/) you want, bring-your-own headless browser service, pull data from your database hosted in another cloud, add your own methods to your Agent and call them. + +Agents built with `agents-sdk` can be deployed directly to Cloudflare and run on top of [Durable Objects](/durable-objects/) — which you can think of as stateful micro-servers that can scale to tens of millions — and are able to run wherever they need to. Run your Agents close to a user for low-latency interactivity, close to your data for throughput, and/or anywhere in between. *** ### Build on the Cloudflare Platform + + +Build serverless applications and deploy instantly across the globe for exceptional performance, reliability, and scale. + + + Observe and control your AI applications with caching, rate limiting, request retries, model fallback, and more. @@ -71,12 +84,6 @@ Run machine learning models, powered by serverless GPUs, on Cloudflare's global - - -Build real-time serverless video, audio and data applications with WebRTC running on Cloudflare's network. - - - Build stateful agents that guarantee executions, including automatic retries, persistent state that runs for minutes, hours, days, or weeks. diff --git a/src/content/docs/agents/platform/agents-vs-workflows.mdx b/src/content/docs/agents/platform/agents-vs-workflows.mdx deleted file mode 100644 index 85ca6a07798e00d..000000000000000 --- a/src/content/docs/agents/platform/agents-vs-workflows.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Agents vs Workflows -pcx_content_type: concept -sidebar: - order: 2 ---- - -import { MetaInfo, Render, Type, WranglerConfig } from "~/components"; - -When should you build an Agent vs a Workflow? - -| Problem to Solve | Agent | Workflows | -|---|---|---| -| Row 1 Col 1 | Row 1 Col 2 | Row 1 Col 3 | -| Row 2 Col 1 | Row 2 Col 2 | Row 2 Col 3 | \ No newline at end of file From 4b22f321951892d1f8f7e9bdc109d285e7288e72 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Tue, 25 Feb 2025 07:29:11 -0500 Subject: [PATCH 38/41] callback --- src/content/docs/agents/examples/schedule-tasks.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/agents/examples/schedule-tasks.mdx b/src/content/docs/agents/examples/schedule-tasks.mdx index cd4e9de03da8bc1..f654eb984bd4268 100644 --- a/src/content/docs/agents/examples/schedule-tasks.mdx +++ b/src/content/docs/agents/examples/schedule-tasks.mdx @@ -39,7 +39,7 @@ export class SchedulingAgent extends Agent { :::caution -Tasks that set a callback for a method that does not exist wil throw an exception. +Tasks that set a callback for a method that does not exist will throw an exception: ensure that the method named in the `callback` argument of `this.schedule` exists on your `Agent` class. ::: From 3740f530b62dfc96e3548b4f6e6954a1851a1479 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Tue, 25 Feb 2025 08:07:49 -0500 Subject: [PATCH 39/41] rag --- .../docs/agents/examples/browse-the-web.mdx | 2 +- src/content/docs/agents/examples/rag.mdx | 87 ++++++++++++++++++- .../docs/agents/examples/run-workflows.mdx | 2 +- src/content/docs/agents/index.mdx | 2 +- 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/content/docs/agents/examples/browse-the-web.mdx b/src/content/docs/agents/examples/browse-the-web.mdx index a8dc7bde779e5a6..703759ceb989095 100644 --- a/src/content/docs/agents/examples/browse-the-web.mdx +++ b/src/content/docs/agents/examples/browse-the-web.mdx @@ -91,7 +91,7 @@ cd your-agent-project-folder npx wrangler@latest secret put BROWSERBASE_API_KEY ``` ```sh output -Enter a secret value: ‚Ķ ****** +Enter a secret value: ****** Creating the secret for the Worker "agents-example" Success! Uploaded secret BROWSERBASE_API_KEY ``` diff --git a/src/content/docs/agents/examples/rag.mdx b/src/content/docs/agents/examples/rag.mdx index d488a6fa3bf802b..c836faa12478995 100644 --- a/src/content/docs/agents/examples/rag.mdx +++ b/src/content/docs/agents/examples/rag.mdx @@ -8,4 +8,89 @@ sidebar: import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; -TODO +Agents can use Retrieval Augmented Generation (RAG) to retrieve relevant information and use it augment [calls to AI models](/agents/examples/using-ai-models/). Store a user's chat history to use as context for future conversations, summarize documents to bootstrap an Agent's knowledge base, and/or use data from your Agent's [web browsing](/agents/examples/browse-the-web/) tasks to enhance your Agent's capabilities. + +You can use the Agent's own [SQL database](/agents/examples/manage-and-sync-state) as the source of truth for your data and store embeddings in [Vectorize](/vectorize/) (or any other vector-enabled database) to allow your Agent to retrieve relevant information. + +### Vector search + +:::note + +If you're brand-new to vector databases and Vectorize, visit the [Vectorize tutorial](/vectorize/get-started/intro/) to learn the basics, including how to create an index, insert data, and generate embeddings. + +::: + +You can query a vector index (or indexes) from any method on your Agent: any Vectorize index you attach is available on `this.env` within your Agent. If you've [associated metadata](/vectorize/best-practices/insert-vectors/#metadata) with your vectors that maps back to data stored in your Agent, you can then look up the data directly within your Agent using `this.sql`. + +Here's an example of how to give an Agent retrieval capabilties: + + + +```ts +import { Agent } from "agents-sdk"; + +interface Env { + AI: Ai; + VECTOR_DB: Vectorize; +} + +export class RAGAgent extends Agent { + // Other methods on our Agent + // ... + // + async queryKnowledge(userQuery: string) { + // Turn a query into an embedding + const queryVector = await this.env.AI.run('@cf/baai/bge-base-en-v1.5', { + text: [userQuery], + }); + + // Retrieve results from our vector index + let searchResults = await this.env.VECTOR_DB.query(queryVector.data[0], { + topK: 10, + returnMetadata: 'all', + }); + + let knowledge = []; + for (const match of searchResults.matches) { + console.log(match.metadata); + knowledge.push(match.metadata); + } + + // Use the metadata to re-associate the vector search results + // with data in our Agent's SQL database + let results = this.sql`SELECT * FROM knowledge WHERE id IN (${knowledge.map((k) => k.id)})`; + + // Return them + return results; + } +} +``` + + + +You'll also need to connect your Agent to your vector indexes: + + + +```jsonc +{ + // ... + "vectorize": [ + { + "binding": "VECTOR_DB", + "index_name": "your-vectorize-index-name" + } + ] + // ... +} +``` + + + +If you have multiple indexes you want to make available, you can provide an array of `vectorize` bindings. + +#### Next steps + +* Learn more on how to [combine Vectorize and Workers AI](/vectorize/get-started/embeddings/) +* Review the [Vectorize query API](/vectorize/reference/client-api/) +* Use [metadata filtering](/vectorize/reference/metadata-filtering/) to add context to your results diff --git a/src/content/docs/agents/examples/run-workflows.mdx b/src/content/docs/agents/examples/run-workflows.mdx index 142aef1e99b9227..d0c9049a95fd3a4 100644 --- a/src/content/docs/agents/examples/run-workflows.mdx +++ b/src/content/docs/agents/examples/run-workflows.mdx @@ -24,7 +24,7 @@ Agents do not have to run to completion: they can loop, branch and run forever, An Agent can trigger one or more Workflows from within any method, whether from an incoming HTTP request, a WebSocket connection, on a delay or schedule, and/or from any other action the Agent takes. -Trigering a Workflow from an Agent is no different from [triggering a Workflow from a Worker script](/workflows/build/trigger-workflows/): +Triggering a Workflow from an Agent is no different from [triggering a Workflow from a Worker script](/workflows/build/trigger-workflows/): diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index 8a0cc11023d81e4..226ee15ab8a6603 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -58,7 +58,7 @@ Agents built with `agents-sdk` can be deployed directly to Cloudflare and run on *** -### Build on the Cloudflare Platform +#### Build on the Cloudflare Platform From f09fa7e779fad780758a8edae3f9ebd44ba30481 Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Tue, 25 Feb 2025 08:30:26 -0500 Subject: [PATCH 40/41] fin --- .../docs/agents/examples/send-emails.mdx | 11 --- .../getting-started/build-a-chat-agent.mdx | 9 ++ .../agents/getting-started/quick-start.mdx | 83 ------------------- .../writing-your-first-agent.mdx | 29 ------- src/content/docs/agents/index.mdx | 4 +- 5 files changed, 11 insertions(+), 125 deletions(-) delete mode 100644 src/content/docs/agents/examples/send-emails.mdx create mode 100644 src/content/docs/agents/getting-started/build-a-chat-agent.mdx delete mode 100644 src/content/docs/agents/getting-started/quick-start.mdx delete mode 100644 src/content/docs/agents/getting-started/writing-your-first-agent.mdx diff --git a/src/content/docs/agents/examples/send-emails.mdx b/src/content/docs/agents/examples/send-emails.mdx deleted file mode 100644 index d3e68647963a695..000000000000000 --- a/src/content/docs/agents/examples/send-emails.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Send emails -pcx_content_type: concept -sidebar: - order: 3 - ---- - -import { MetaInfo, Render, Type, TypeScriptExample, WranglerConfig } from "~/components"; - -TODO diff --git a/src/content/docs/agents/getting-started/build-a-chat-agent.mdx b/src/content/docs/agents/getting-started/build-a-chat-agent.mdx new file mode 100644 index 000000000000000..0c6f329b147e1f7 --- /dev/null +++ b/src/content/docs/agents/getting-started/build-a-chat-agent.mdx @@ -0,0 +1,9 @@ +--- +pcx_content_type: navigation +title: Build a Chat Agent +external_link: https://github.com/cloudflare/agents-starter +sidebar: + order: 3 +head: [] +description: A starter template for building AI-powered chat agents using Cloudflare's Agent platform, powered by agents-sdk. This project provides a foundation for creating interactive chat experiences with AI, complete with a modern UI and tool integration capabilities. +--- diff --git a/src/content/docs/agents/getting-started/quick-start.mdx b/src/content/docs/agents/getting-started/quick-start.mdx deleted file mode 100644 index de0506193fc9f98..000000000000000 --- a/src/content/docs/agents/getting-started/quick-start.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: Quick start -pcx_content_type: get-started -sidebar: - order: 2 - ---- - -import { Render, FileTree, PackageManagers, TypeScriptExample, WranglerConfig } from "~/components" - -:::note - -**This quick-start guide will get you deploying your first Agent on Cloudflare in less than 5 minutes.** - -If you're new to Cloudflare Workers, Agents, or Cloudflare in general, we recommend following the more comprehensive [Agents tutorial](/agents/getting-started/writing-your-first-agent/), ihich takes you through the process step-by-step. - -::: - -## Prerequisites - - - -## 1. Create a new Agent - -You can get started by using the `cloudflare/agents-starter` template to create a new project: - - - -This will create a new directory called `my-agent` with several files, including: - - -- **wrangler.jsonc** project configuration -- src - - **index.ts** **where your Agent's code is defined** -- test - - index.spec.ts **where your tests are defined** -- ... - - -## 2. Review the code - -Open up `src/index.ts` in your favorite text editor: - - - -```ts -import { Agent } from "agents-sdk"; - -export class MyAgent extends Agent { - -} -``` - - - -## 3. Deploy your Agent - -Agents are deployed just like any other Workers application: - -```sh -npx wrangler@latest deploy -``` -```sh output -TODO -``` - -## 4. Run your Agent - -TODO - -## 5. Build out your Agent - -OK, so you have an Agent deployed and running. What's next? - -- Understand more about the [Agent framework API](/agents/api-reference/sdk/) -- [Call AI models](/agents/examples/using-ai-models/) from your Agent -- Learn how to [persist state to and query data stored in](/agents/examples/manage-and-sync-state/) your Agent -- Run [scheduled tasks](/agents/examples/schedule-tasks/) -- Trigger [asynchronous workflows](/agents/examples/run-workflows/) that your Agent can co-ordinate and manage diff --git a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx b/src/content/docs/agents/getting-started/writing-your-first-agent.mdx deleted file mode 100644 index d25acb45ae82385..000000000000000 --- a/src/content/docs/agents/getting-started/writing-your-first-agent.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Writing your first Agent -pcx_content_type: get-started -sidebar: - order: 1 - ---- - -import { Render, PackageManagers, TypeScriptExample, WranglerConfig } from "~/components" - -:::note - -New to building Agents and/or using Cloudflare Workers? This tutorial will guide you through the process of creating your first Agent and deploying it live. - -If you're familiar with Workers, you can head over to our [quick start guide](/agents/getting-started/quick-start/) or review the [Agents API Reference](/agents/api-reference/sdk). - -::: - -### Prerequisites - - - -### 1. Create an Agents project - - diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index 226ee15ab8a6603..dc8b18cffe5ab6e 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -27,11 +27,11 @@ Build and deploy AI-powered Agents on Cloudflare that can autonomously perform t #### Ship your first Agent -Use the agent started template to create your first Agent: +Use the agent started template to create your first Agent with the `agents-sdk`: ```sh # install it -npm create cloudflare@latest -- --template=cloudflare/agents-starter +npm create cloudflare@latest agents-starter -- --template=cloudflare/agents-starter # and deploy it npx wrangler@latest deploy ``` From 2d777dd659025defc71e8a16037e67c2eafafbcd Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Tue, 25 Feb 2025 08:46:18 -0500 Subject: [PATCH 41/41] fix links --- src/content/docs/agents/index.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/agents/index.mdx b/src/content/docs/agents/index.mdx index dc8b18cffe5ab6e..701e8f694d16fdd 100644 --- a/src/content/docs/agents/index.mdx +++ b/src/content/docs/agents/index.mdx @@ -36,7 +36,7 @@ npm create cloudflare@latest agents-starter -- --template=cloudflare/agents-star npx wrangler@latest deploy ``` -Head to the [getting started tutorial](/agents/getting-started/writing-your-first-agent/) to dive into shipping your first Agent on Cloudflare. +Head to the guide on [building a chat agent](/agents/getting-started/build-a-chat-agent) to learn how to build and deploy an Agent to prod. If you're already building on [Workers](/workers/), you can install the `agents-sdk` package directly into an existing project: @@ -51,7 +51,7 @@ Dive into the [Agent SDK reference](/agents/api-reference/sdk/) to learn more ab We built the `agents-sdk` with a few things in mind: - **Batteries (state) included**: Agents come with [built-in state management](/agents/examples/manage-and-sync-state/), with the ability to automatically sync state between an Agent and clients, trigger events on state changes, and read+write to each Agent's SQL database. -- **Communicative**: You can connect to an Agent via [WebSockets](/agents/examples/websockets/) and stream updates back to client in real-time. Handle a long-running response from a reasoning model, the results of an [asynchronous workflow](/agents/examples/asynchronous-workflows/), or build a chat app that builds on the `useAgent` hook included in the `agents-sdk`. +- **Communicative**: You can connect to an Agent via [WebSockets](/agents/examples/websockets/) and stream updates back to client in real-time. Handle a long-running response from a reasoning model, the results of an [asynchronous workflow](/agents/examples/run-workflows/), or build a chat app that builds on the `useAgent` hook included in the `agents-sdk`. - **Extensible**: Agents are code. Use the [AI models](/agents/examples/using-ai-models/) you want, bring-your-own headless browser service, pull data from your database hosted in another cloud, add your own methods to your Agent and call them. Agents built with `agents-sdk` can be deployed directly to Cloudflare and run on top of [Durable Objects](/durable-objects/) — which you can think of as stateful micro-servers that can scale to tens of millions — and are able to run wherever they need to. Run your Agents close to a user for low-latency interactivity, close to your data for throughput, and/or anywhere in between.