CLAUDE.md
generative_ui_agents/generative-ui-starter-project/CLAUDE.mdCLAUDE.md
Quality
85/100
Scores the file, not the repository.Length
1,170 words
23 headings · 10 code blocksRepository
130k
— · pushed 1 days agoLast changed
3 days ago
First indexed 3 days ago.1# CopilotKit + LangGraph Todo Demo23## Purpose45This repository serves as both a **showcase** and **template** for building AI agents with CopilotKit and LangGraph. It demonstrates how CopilotKit can drive interactive UI beyond just chat, using a **collaborative todo list** as the primary example.67**Target audience:** Developers evaluating CopilotKit or starting new projects with AI agents.89## Core Concept1011The todo list demonstrates **agent-driven UI** where:1213- The agent can manipulate application state (adding todos, updating status, organizing tasks)14- Users can interact with the same state (editing titles, checking off tasks, deleting todos)15- Both agent and user changes update the same shared state16- The UI reactively updates based on agent state changes1718This uses CopilotKit's **v2 agent state pattern** where state lives in the agent and syncs to the frontend.1920## Architecture2122This is a **flat npm project** with a Next.js frontend at the root and a Python agent in `agent/`.2324### Repository Structure2526```27├── src/28│ ├── app/29│ │ ├── page.tsx # Main page - wires up all components30│ │ └── api/copilotkit/ # CopilotKit API route31│ ├── components/32│ │ ├── canvas/ # Todo list UI33│ │ │ ├── index.tsx # Canvas container34│ │ │ ├── todo-list.tsx # Todo list with columns35│ │ │ ├── todo-column.tsx # Column (pending/completed)36│ │ │ └── todo-card.tsx # Individual todo card37│ │ ├── example-layout/ # Layout: chat + canvas side-by-side38│ │ └── generative-ui/ # Example generative UI components39│ └── hooks/40│ ├── use-generative-ui-examples.tsx # Example CopilotKit patterns41│ └── use-example-suggestions.tsx # Chat suggestions42├── agent/ # LangGraph Python agent43│ ├── main.py # Agent entry point44│ └── src/45│ ├── todos.py # Todo tools and state schema46│ └── query.py # Example data query tool47├── scripts/ # Agent setup and run scripts48│ ├── setup-agent.sh / .bat49│ └── run-agent.sh / .bat50├── package.json # Root project config (npm + concurrently)51└── next.config.ts52```5354## Key Pattern: Agent State with CopilotKit v25556The todo list uses **CopilotKit v2's agent state pattern** where state lives in the agent backend and syncs bidirectionally with the frontend.5758### How It Works59601. **Agent defines state schema and tools** (Python)6162```python63 # agent/src/todos.py64 class Todo(TypedDict):65 id: str66 title: str67 description: str68 emoji: str69 status: Literal["pending", "completed"]7071 class AgentState(TypedDict):72 todos: list[Todo]7374 @tool75 def manage_todos(todos: list[Todo], runtime: ToolRuntime) -> Command:76 """Manage the current todos."""77 return Command(update={"todos": todos, ...})78```79802. **Frontend reads from agent state**8182```typescript83 // src/components/canvas/index.tsx84 const { agent } = useAgent();8586 return (87 <TodoList88 todos={agent.state?.todos || []}89 onUpdate={(updatedTodos) => agent.setState({ todos: updatedTodos })}90 isAgentRunning={agent.isRunning}91 />92 );93```94953. **User interactions update agent state**9697```typescript98 // User clicks checkbox → frontend calls agent.setState()99 const toggleStatus = (todo) => {100 const updated = todos.map((t) =>101 t.id === todo.id102 ? { ...t, status: t.status === "completed" ? "pending" : "completed" }103 : t,104 );105 agent.setState({ todos: updated });106 };107```1081094. **Agent can manipulate state via tools**110 - The agent calls `manage_todos` tool to update the todo list111 - Both user and agent changes update the same `agent.state.todos`112 - Frontend automatically re-renders when state changes113114### Why This Pattern?115116- **Single source of truth**: State lives in the agent, not duplicated in frontend117- **Bidirectional sync**: User changes → agent state, Agent changes → UI update118- **Simple**: No need for separate frontend state management119- **Observable**: Agent has full visibility into state changes120121## Implementation Details122123### Agent Backend124125**Agent Definition** (`agent/main.py`):126127```python128from langchain.agents import create_agent129from copilotkit import CopilotKitMiddleware130from src.todos import todo_tools, AgentState131132agent = create_agent(133 model="gpt-5.5",134 tools=[*todo_tools, ...], # manage_todos, get_todos135 middleware=[CopilotKitMiddleware()],136 state_schema=AgentState, # Defines state shape137 system_prompt="You are a helpful assistant..."138)139```140141**Todo Tools** (`agent/src/todos.py`):142143```python144@tool145def manage_todos(todos: list[Todo], runtime: ToolRuntime) -> Command:146 """Manage the current todos."""147 # Ensure todos have unique IDs148 for todo in todos:149 if "id" not in todo or not todo["id"]:150 todo["id"] = str(uuid.uuid4())151152 # Update agent state153 return Command(update={154 "todos": todos,155 "messages": [ToolMessage(...)]156 })157158@tool159def get_todos(runtime: ToolRuntime):160 """Get the current todos."""161 return runtime.state.get("todos", [])162```163164### Frontend165166**Canvas Component** (`src/components/canvas/index.tsx`):167168```typescript169export function Canvas() {170 const { agent } = useAgent(); // CopilotKit v2 hook171172 return (173 <div className="h-full p-8 bg-gray-50">174 <TodoList175 // Read state from agent176 todos={agent.state?.todos || []}177 // Update state in agent178 onUpdate={(updatedTodos) => agent.setState({ todos: updatedTodos })}179 // React to agent execution180 isAgentRunning={agent.isRunning}181 />182 </div>183 );184}185```186187**Todo List** (`src/components/canvas/todo-list.tsx`):188189```typescript190export function TodoList({ todos, onUpdate, isAgentRunning }: TodoListProps) {191 const toggleStatus = (todo: Todo) => {192 const updated = todos.map((t) =>193 t.id === todo.id194 ? { ...t, status: t.status === "completed" ? "pending" : "completed" }195 : t196 );197 onUpdate(updated); // Calls agent.setState()198 };199200 const addTodo = () => {201 const newTodo = { id: crypto.randomUUID(), ... };202 onUpdate([...todos, newTodo]);203 };204205 return (206 <div className="flex gap-8">207 <TodoColumn title="To Do" todos={pendingTodos} onAddTodo={addTodo} ... />208 <TodoColumn title="Done" todos={completedTodos} ... />209 </div>210 );211}212```213214### How State Flows2152161. **User adds/edits todo** → Frontend calls `agent.setState({ todos: [...] })`2172. **Agent state updates** → CopilotKit syncs to backend2183. **Agent observes change** → Can respond via `manage_todos` tool2194. **Agent modifies todos** → Calls `manage_todos` tool2205. **State syncs to frontend** → `agent.state.todos` updates2216. **UI re-renders** → React sees new state and updates display222223**Key insight**: State lives in the agent, frontend just reads/writes to it via CopilotKit hooks.224225## Tech Stack226227- **Frontend**: Next.js 16, React 19, TailwindCSS 4228- **Agent**: LangGraph (Python), OpenAI GPT-5.2229- **CopilotKit**: React hooks for agent integration (v2)230- **Build**: npm with concurrently for parallel dev processes231- **Other**: Recharts for generative UI examples232233## Development234235```bash236# Install dependencies (also sets up agent via postinstall)237npm install238239# Start both frontend and agent240npm run dev241242# Start individually243npm run dev:ui # Next.js frontend on port 3000244npm run dev:agent # LangGraph agent on port 8123245246# Build247npm run build248```249250### Environment Setup251252```bash253# Set OpenAI API key254cp .env.example .env255# Edit .env and add your OPENAI_API_KEY256```257258## Design Principles2592601. **Simple over complex** - The todo list is intentionally simple and focused2612. **CopilotKit v2 patterns** - Uses modern agent state management2623. **Template-first** - Code is meant to be forked and extended2634. **Showcasing agent-driven UI** - Demonstrates AI manipulating application state beyond chat264265---266267## Key Takeaways for Developers268269**State Management Pattern**: This app uses CopilotKit v2's agent state pattern where:270271- State is defined in the agent backend (Python TypedDict)272- Frontend reads via `agent.state.todos`273- Frontend writes via `agent.setState({ todos: ... })`274- Agent can modify state via tools (`manage_todos`)275- Changes sync bidirectionally automatically276277**When extending this template**:278279- Define state schema in the agent (`AgentState`)280- Create tools that manipulate state via `Command(update={...})`281- Use `useAgent()` hook in frontend to read/write state282- Let CopilotKit handle the sync - no manual state management needed283284This pattern works great for **agent-driven applications** where the AI needs to manipulate structured application state, not just chat.285
Also in Shubhamsaboo/awesome-llm-apps
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| Shubhamsaboo/awesome-llm-appsgenerative_ui_agents/ai-dashboard-canvas-agent/AGENTS.md · 130k | AGENTS.md | setupbuildtestlint-format+6 | 86/100 | 3 days ago |
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| Adit-Jain-srm/NightmareNetCLAUDE.md · 45 | CLAUDE.md | buildtestlint-formatstyle+6 | 100/100 | 3 days ago | |
| nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.4k | CLAUDE.md | setupbuildstylearch+2 | 100/100 | 3 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 3 days ago | |
| microsoft/playwrightCLAUDE.md · 94k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 3 days ago | |
| dotCMS/coreCLAUDE.md · 949 | CLAUDE.md | setupbuildteststyle+7 | 99/100 | today | |
| lollipopkit/flutter_server_boxCLAUDE.md · 8.3k | CLAUDE.md | buildteststylearch+2 | 98/100 | 3 days ago | |
| carrot-foundation/middle-earthCLAUDE.md · 0 | CLAUDE.md | setupbuildtestlint-format+6 | 97/100 | 3 days ago | |
| khrnchn/sedekah-jeCLAUDE.md · 89 | CLAUDE.md | testlint-formatstylearch+6 | 97/100 | 3 days ago |
