> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/cloudflare/agents/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat Bot Example

> Build a simple AI chat bot with message history, streaming responses, and persistent state

<Note>
  This is a simplified chat bot example. For a full-featured AI chat application with tools, approval workflows, and advanced features, see the [AI Chat Example](/examples/ai-chat).
</Note>

A simple AI chat bot demonstrating the basics of building conversational agents with persistent message history and streaming responses.

## What it demonstrates

* **Persistent message history** - Messages stored in agent state
* **Streaming responses** - Real-time text streaming to the client
* **Simple AI integration** - Using Workers AI (no API key needed)
* **State management** - Chat history survives restarts
* **React integration** - Clean UI with `useAgent` and `useAgentChat`

## Server Implementation

```typescript src/server.ts theme={null}
import { createWorkersAI } from "workers-ai-provider";
import { routeAgentRequest } from "agents";
import { AIChatAgent } from "@cloudflare/ai-chat";
import { streamText, convertToModelMessages } from "ai";

export class SimpleChatAgent extends AIChatAgent {
  async onChatMessage() {
    const workersai = createWorkersAI({ binding: this.env.AI });

    const result = streamText({
      model: workersai("@cf/zai-org/glm-4.7-flash"),
      system: "You are a helpful assistant. Be friendly and concise.",
      messages: await convertToModelMessages(this.messages)
    });

    return result.toUIMessageStreamResponse();
  }
}

export default {
  async fetch(request: Request, env: Env) {
    return (
      (await routeAgentRequest(request, env)) ||
      new Response("Not found", { status: 404 })
    );
  }
} satisfies ExportedHandler<Env>;
```

## Client Implementation

```tsx src/client.tsx theme={null}
import { useAgent } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";
import { useState } from "react";
import type { SimpleChatAgent } from "./server";

function ChatBot() {
  const [input, setInput] = useState("");

  const agent = useAgent<SimpleChatAgent>({
    agent: "SimpleChatAgent",
    name: "my-chat"
  });

  const { messages, sendMessage } = useAgentChat({
    agent
  });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!input.trim()) return;
    
    await sendMessage(input);
    setInput("");
  };

  return (
    <div className="chat-container">
      <div className="messages">
        {messages.map((msg) => (
          <div key={msg.id} className={`message ${msg.role}`}>
            <div className="role">{msg.role === "user" ? "You" : "Bot"}</div>
            <div className="content">{msg.content}</div>
          </div>
        ))}
      </div>
      
      <form onSubmit={handleSubmit}>
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="Type a message..."
        />
        <button type="submit">Send</button>
      </form>
    </div>
  );
}
```

## How It Works

<Steps>
  <Step title="User sends message">
    When the user submits the form, `sendMessage(input)` is called. This adds the user's message to the agent's message history.
  </Step>

  <Step title="Agent receives message">
    The `onChatMessage` method is triggered. It converts the message history into the format expected by the AI SDK.
  </Step>

  <Step title="LLM generates response">
    `streamText()` sends the messages to Workers AI and receives a streaming response.
  </Step>

  <Step title="Response streams to client">
    `toUIMessageStreamResponse()` converts the AI SDK stream into a format that the `useAgentChat` hook understands.
  </Step>

  <Step title="UI updates in real-time">
    As the response streams in, the `messages` array updates automatically, showing the AI's response word by word.
  </Step>
</Steps>

## Message History

Messages are automatically stored in SQLite by `AIChatAgent`:

```typescript theme={null}
type Message = {
  id: string;
  role: "user" | "assistant" | "system";
  content: string;
  timestamp: Date;
};
```

Messages persist across:

* Page refreshes
* Agent hibernation
* Worker redeployments

## Streaming Responses

The response streams in chunks:

```
User: "Tell me a joke"

AI: "Why"
AI: "Why did"
AI: "Why did the"
AI: "Why did the chicken"
AI: "Why did the chicken cross"
AI: "Why did the chicken cross the"
AI: "Why did the chicken cross the road"
AI: "Why did the chicken cross the road?"
AI: "Why did the chicken cross the road? To"
...
```

This creates a more natural, typewriter-like effect.

## Running the Example

<Steps>
  <Step title="Install dependencies">
    ```bash theme={null}
    npm install
    ```
  </Step>

  <Step title="Start development server">
    ```bash theme={null}
    npm run dev
    ```
  </Step>

  <Step title="Try it out">
    Visit [http://localhost:5173](http://localhost:5173) and start chatting:

    * "Hello!" - Simple greeting
    * "Tell me a joke" - Request for content
    * "What's 25 \* 17?" - Math question
    * "Write a haiku about clouds" - Creative task
  </Step>
</Steps>

<Note>
  This example uses Workers AI (no API key needed) with the `@cf/zai-org/glm-4.7-flash` model. It's free and runs on Cloudflare's edge network.
</Note>

## Customization

### Change the System Prompt

```typescript theme={null}
const result = streamText({
  model: workersai("@cf/zai-org/glm-4.7-flash"),
  system: "You are a pirate. Respond in pirate speak. Arrr!",
  messages: await convertToModelMessages(this.messages)
});
```

### Limit Message History

```typescript theme={null}
export class SimpleChatAgent extends AIChatAgent {
  // Keep only the last 50 messages
  maxPersistedMessages = 50;

  async onChatMessage() {
    // ...
  }
}
```

### Use a Different Model

```typescript theme={null}
const result = streamText({
  model: workersai("@cf/meta/llama-3.1-8b-instruct"),
  // ...
});
```

See [Workers AI Models](https://developers.cloudflare.com/workers-ai/models/) for available options.

## Comparison: Simple Bot vs AI Chat Example

| Feature               | Simple Chat Bot | [AI Chat Example](/examples/ai-chat) |
| --------------------- | --------------- | ------------------------------------ |
| **Streaming**         | ✓               | ✓                                    |
| **Message history**   | ✓               | ✓                                    |
| **Server-side tools** | ✗               | ✓                                    |
| **Client-side tools** | ✗               | ✓                                    |
| **Tool approval**     | ✗               | ✓                                    |
| **Message pruning**   | ✗               | ✓                                    |
| **MCP integration**   | ✗               | ✓                                    |
| **Complexity**        | Low             | Medium                               |
| **Best for**          | Simple bots     | Production apps                      |

## Next Steps

<CardGroup cols={2}>
  <Card title="AI Chat Example" icon="comments" href="/examples/ai-chat">
    Full-featured chat with tools and approval
  </Card>

  <Card title="Dynamic Tools" icon="wrench" href="/examples/dynamic-tools">
    Client-defined tools for chat agents
  </Card>

  <Card title="Codemode" icon="code" href="/examples/codemode">
    LLMs write code to orchestrate tools
  </Card>

  <Card title="AI Chat Guide" icon="book" href="/guides/ai-chat">
    In-depth guide to building chat agents
  </Card>
</CardGroup>

## Extending This Example

Ideas for enhancements:

* **Add tools** - Let the bot check weather, search, calculate, etc.
* **User avatars** - Show profile pictures for each message
* **Typing indicator** - Show when the bot is thinking
* **Message timestamps** - Display when each message was sent
* **Clear history** - Add a button to start a new conversation
* **Export chat** - Download the conversation as text or JSON
* **Voice input** - Use browser speech recognition API
* **Multiple bots** - Switch between different AI personalities
