A simple, well-documented example agent for the Whatever OS platform. Perfect for learning how to build AI agents with the Claude Agent SDK.
- Generates QR codes for URLs, text, and any content
- Displays QR codes in a beautiful UI card
- Demonstrates all core agent concepts with clear documentation
# 1. Install dependencies
npm install
# 2. Copy environment file
cp .env.example .env
# 3. Add your Anthropic API key to .env
# ANTHROPIC_API_KEY=sk-ant-...
# 4. Start the development server
npm run devThe agent runs on http://localhost:3003 by default.
example-agent/
βββ app/ # Next.js App Router
β βββ api/
β β βββ process/route.ts # Main message processing endpoint
β β βββ health/route.ts # Health check endpoint
β β βββ ui/[id]/route.ts # UI data endpoint for iframes
β β βββ iframe-config/route.ts # Iframe display configuration
β βββ frames/
β β βββ qr-code/page.tsx # QR code iframe page
β β βββ lib/fetch-ui-data.ts # Data fetching utility
β β βββ layout.tsx # Frames layout
β βββ welcome/page.tsx # Welcome screen
β βββ layout.tsx # Root layout
β
βββ components/
β βββ ui-frames/
β βββ qr-frame.tsx # QR code display component
β
βββ lib/
β βββ agent.ts # β Main agent class
β βββ tools.ts # β MCP tools (QR generation)
β βββ system-prompt.ts # β System prompt
β βββ ui-store.ts # UI data storage
β βββ settings.json # Agent settings
β βββ core/ # Agent framework
β βββ base-agent.ts # Base agent class
β βββ orchestrator.ts # Claude SDK integration
β βββ types.ts # TypeScript types
β βββ schema-utils.ts # JSON schema helpers
β βββ iframe-config.ts # Iframe config types
β
βββ README.md # This file!
Tools are actions the AI can perform. Define them with:
- Name: Unique identifier
- Description: Helps AI understand when to use it
- Schema: Zod schema for input validation
- Handler: Async function that executes the action
import { tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";
const generateQR = tool(
"generate_qr", // Name
"Generate a QR code from text or URL", // Description
{ // Input schema
content: z.string(),
size: z.number().optional().default(300),
},
async ({ content, size }) => { // Handler
const dataUrl = await QRCode.toDataURL(content, { width: size });
return {
content: [{ type: "text", text: JSON.stringify({ dataUrl, content }) }]
};
}
);The system prompt defines the AI's personality and behavior:
const SYSTEM_PROMPT = `You are QR Code Generator, a helpful assistant...
## Your Capabilities
- Generate QR codes for URLs and text
- Customize colors and sizes
## Response Format
Use ui_data with type "qr_code" to display QR codes.
`;The agent class ties everything together:
class ExampleAgent extends BaseAgent {
readonly config = { id: "example", name: "QR Generator", ... };
getMcpServer() { return exampleMcpServer; }
async buildSystemPrompt() { return buildSystemPrompt(); }
getFrameUrl(type: string) { /* Map UI types to iframe URLs */ }
}Rich UI components rendered in iframes:
User asks for QR code
β
Agent generates QR code using tool
β
Agent returns ui_data: { type: "qr_code", dataUrl: "...", content: "..." }
β
UI data stored with unique ID
β
Platform loads iframe: /frames/qr-code?id=abc123
β
Iframe fetches data from /api/ui/abc123
β
Beautiful QR code card displayed!
| Endpoint | Method | Description |
|---|---|---|
/api/process |
POST | Process user messages (main endpoint) |
/api/health |
GET | Health check |
/api/ui/[id] |
GET | Fetch UI data for iframes |
/api/iframe-config |
GET | Get iframe display config |
- Define the tool in
lib/tools.ts:
const myNewTool = tool(
"my_tool",
"Description of what it does",
{ input: z.string() },
async ({ input }) => {
// Do something
return { content: [{ type: "text", text: "result" }] };
}
);
// Add to allTools array
const allTools = [generateQR, myNewTool];- Update the system prompt to mention the new capability
- Create the frame component in
components/ui-frames/ - Create the frame page in
app/frames/my-type/page.tsx - Update
lib/agent.ts:- Add to
EXAMPLE_UI_TYPES - Add properties to
EXAMPLE_UI_PROPERTIES - Add route mapping in
getFrameUrl()
- Add to
Edit lib/system-prompt.ts to change the agent's personality, capabilities, and response format.
| Variable | Description | Default |
|---|---|---|
ANTHROPIC_API_KEY |
Your Anthropic API key | Required |
AGENT_ID |
Agent ID (match platform registration) | example |
PLATFORM_JWKS_URL |
Platform's JWKS endpoint for JWT verification | http://localhost:3000/.well-known/jwks.json |
AGENT_BASE_URL |
Agent's base URL for iframe URLs | http://localhost:3003 |
NEXT_PUBLIC_AGENT_URL |
Public URL for client-side fetches | http://localhost:3003 |
- Deploy to Vercel, Railway, or your hosting provider
- Set environment variables in your hosting dashboard
- Register the agent in the Whatever platform's
agentstable:
INSERT INTO agents (id, name, description, base_url, is_public, price)
VALUES (
'example',
'QR Generator',
'Generate QR codes for URLs and text',
'https://your-agent.vercel.app',
true,
0
);βββββββββββββββββββββββ βββββββββββββββββββββββ
β Whatever Platform ββββββΆβ Example Agent β
β (sends messages) βββββββ (processes them) β
βββββββββββββββββββββββ βββββββββββββββββββββββ
β β
β βΌ
β βββββββββββββββββββ
β β Claude Agent β
β β SDK β
β ββββββββββ¬βββββββββ
β β
β βΌ
β βββββββββββββββββββ
β β MCP Tools β
β β (generate_qr) β
β βββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Iframe (QR code) ββββββ Loads UI data from agent
βββββββββββββββββββββββ
- Start the agent:
npm run dev - Open
http://localhost:3003/welcometo see the welcome screen - Use the Whatever platform to chat with the agent
- Ask: "Create a QR code for https://example.com"
Try these exercises:
- Add Color Support: Update the QR frame to accept custom colors
- Add WiFi QR Codes: Create a special tool for WiFi credentials
- Add History: Store generated QR codes in a database
Add AGENT_ID=example to your .env file.
Make sure PLATFORM_JWKS_URL points to the running platform.
Check that AGENT_BASE_URL and NEXT_PUBLIC_AGENT_URL are set correctly.
MIT - Feel free to use this as a starting point for your own agents!