Agent Overview
AI chat agent powered by Cloudflare Durable Objects, VoltAgent Core, and Convex
AI Agent Overview
A fully-featured AI chat agent built on Cloudflare Durable Objects with VoltAgent Core's PlanAgent for multi-step task decomposition, integrated with Convex for data persistence and Daytona for sandboxed code execution.
Key Features
Multi-Step Planning with Sub-Agents
The agent uses VoltAgent Core's PlanAgent to decompose complex tasks into steps, delegating specialized work to sub-agents:
const agent = new PlanAgent({
name: "Assistant",
systemPrompt: SYSTEM_PROMPT,
model: createAiClient(model, reasoningEffort),
tools: [webSearchToolkit, askUserToolkit],
task: {
taskDescription: TASK_PROMPT,
supervisorConfig: {
fullStreamEventForwarding: {
types: ["text-delta", "reasoning-delta", "tool-call", "tool-result", ...],
},
},
},
subagents: [daytonaSubAgent],
maxSteps: 100,
});Multi-Model Support
Switch between LLM providers through OpenRouter. Default model: openai/gpt-5.2-chat.
| Provider | Example Models |
|---|---|
| OpenAI | GPT-5.2 Chat, GPT-4o, o3 |
| Anthropic | Claude 4 Opus, Claude 3.5 Sonnet |
| Gemini 2.5 Pro | |
| DeepSeek | DeepSeek R1, DeepSeek V3 |
Reasoning Support
Extended thinking with configurable effort levels (low, medium, high) passed through to OpenRouter:
const model = createAiClient("openai/o3", "medium");Sandbox Tools (Daytona)
Each chat can have an attached Daytona sandbox with full filesystem and terminal access:
- File operations -- list, read, write, edit, glob, grep
- Shell execution -- run arbitrary commands
- PTY terminals -- persistent terminal sessions with streaming output, resize, and close
- Code interpreter -- stateful Python execution in notebook-like contexts
- Download URLs -- generate direct file download links
Web Search (Exa)
Neural search via Exa with category filtering, domain scoping, and date ranges. Results include text content, URLs, and metadata. Source citations are enforced inline.
Ask User
Structured question tool that pauses execution to gather user input. Supports multiple questions (1-4), predefined options with descriptions, multi-select, and custom "Other" responses.
Vector Search (RAG)
Chat messages are indexed in Cloudflare Vectorize (768 dimensions, cosine similarity). Before generating a response, the agent queries for relevant past messages across the user's chats and injects them as retrieval context.
Real-Time Streaming
Full event forwarding from PlanAgent to the frontend:
text-delta-- incremental text tokensreasoning-delta-- reasoning/thinking tokenstool-input-start,tool-input-delta,tool-input-end-- tool argument streamingtool-call,tool-result,tool-error-- tool execution lifecyclesource,error,finish-- metadata events
Background Task Execution
Long-running tool calls can execute in the background with configurable timeout (default: 1 hour). The task tool from PlanAgent is patched with background support, allowing up to 30-minute foreground execution with optional background continuation.
Authentication
Dual auth strategy via ConvexAdapter:
- JWT tokens -- standard Convex auth tokens
- External tokens -- shared secret for service-to-service calls
Token is parsed from WebSocket URL params. The adapter routes to the correct Convex query/mutation variants based on token type.
Tech Stack
| Component | Technology |
|---|---|
| Agent Runtime | Cloudflare Durable Objects (AIChatAgent) |
| Orchestration | VoltAgent Core (PlanAgent + sub-agents) |
| LLM Gateway | OpenRouter API |
| Sandbox | Daytona SDK (filesystem, PTY, code interpreter) |
| Web Search | Exa neural search |
| Vector Store | Cloudflare Vectorize |
| Streaming | Vercel AI SDK (createUIMessageStream) |
| Backend | Convex |
| Observability | VoltAgent VoltOps (optional) |
| Infrastructure | Alchemy (IaC for Cloudflare) |
How It Works
- WebSocket connects -- Frontend opens a connection to a Durable Object identified by chat ID, passing auth token, model, and reasoning effort as URL params
- Agent initializes --
onConnectcreates theConvexAdapter, fetches the chat document, initializes Daytona sandbox, registers callable PTY/FS functions, and builds thePlanAgentwith sub-agents - Message received --
onChatMessageupdates the chat timestamp, generates a title on the first message, builds RAG context from Vectorize, and streams viaPlanAgent.streamText() - Messages persist --
persistMessagesindexes messages in the vector store for future retrieval - State syncs -- Frontend can update model/reasoning settings via
setState(), which patches the agent and sub-agent models in real-time
Getting Started
Required environment variables:
OPENROUTER_API_KEY=sk-or-v1-xxxx
CONVEX_URL=https://your-deployment.convex.cloud
CONVEX_SITE_URL=https://your-deployment.convex.site
SITE_URL=https://your-app.com
VITE_AGENT_URL=https://your-agent.workers.dev # Frontend .envContinue to Architecture to understand how the agent system is built.