### Frontend Setup with pnpm Source: https://github.com/ag-ui-protocol/open-ag-ui-canvas/blob/main/README.md Installs frontend dependencies using pnpm within the 'frontend' directory of the cloned repository. This prepares the Next.js application for development. ```bash cd frontend pnpm install ``` -------------------------------- ### Agent Setup with Poetry and pip Source: https://github.com/ag-ui-protocol/open-ag-ui-canvas/blob/main/README.md Installs Python backend dependencies using Poetry and then installs the 'crewai' library using pip. This is required for running the AGUI protocol agents. ```bash cd agent poetry install pip install crewai ``` -------------------------------- ### Run Python FastAPI Agent Server Source: https://github.com/ag-ui-protocol/open-ag-ui-canvas/blob/main/README.md Starts the FastAPI backend server for the AGUI protocol agents using Poetry. This command makes the agent logic accessible to the frontend. ```bash poetry run python main.py ``` -------------------------------- ### Run Next.js Frontend Development Server Source: https://github.com/ag-ui-protocol/open-ag-ui-canvas/blob/main/README.md Starts the Next.js development server for the frontend application. This command allows you to view and interact with the canvas applications in your browser. ```bash pnpm run dev ``` -------------------------------- ### Run Agent Server from Frontend Directory Source: https://github.com/ag-ui-protocol/open-ag-ui-canvas/blob/main/README.md Starts the agent server from within the frontend directory using a specific pnpm script. This command might be a convenience shortcut for development. ```bash //Need to be inside frontend directory cd frontend pnpm run dev:agent ``` -------------------------------- ### Clone AGUI Protocol Repository Source: https://github.com/ag-ui-protocol/open-ag-ui-canvas/blob/main/README.md Clones the open-ag-ui-canvas repository from GitHub and navigates into the project directory. This is the initial step for setting up the project locally. ```bash git clone https://github.com/ag-ui-protocol/open-ag-ui-canvas cd open-ag-ui-canvas ``` -------------------------------- ### Python FastAPI CopilotKit Agent Server Source: https://context7.com/ag-ui-protocol/open-ag-ui-canvas/llms.txt This Python script sets up a FastAPI server that integrates CopilotKit SDK with LangGraph and CrewAI agents. It exposes an endpoint at '/copilotkit' for AI agent communication. Dependencies include 'fastapi', 'uvicorn', and '@copilotkit/sdk'. ```python #agent/main.py from fastapi import FastAPI import uvicorn from copilotkit import CopilotKitSDK, LangGraphAgent from copilotkit.crewai import CrewAIAgent from copilotkit.integrations.fastapi import add_fastapi_endpoint from research_langgraph import graph from planner_crew import PlannerFlow import os app = FastAPI() sdk = CopilotKitSDK( agents=[ LangGraphAgent( name="langgraphAgent", description="An agent that can help you with your research.", graph=graph ), CrewAIAgent( name="crewaiAgent", description="An agent that can help with planning a project", flow=PlannerFlow(), ), ] ) add_fastapi_endpoint(app, sdk, "/copilotkit") @app.get("/") def read_root(): return {"message": "Hello, World!"} if __name__ == "__main__": port = int(os.getenv("PORT", "8000")) uvicorn.run("main:app", host="0.0.0.0", port=port) ``` -------------------------------- ### Planner Agent with CopilotKit Stream Source: https://context7.com/ag-ui-protocol/open-ag-ui-canvas/llms.txt Python implementation for a planning agent using CrewAI and CopilotKit. It defines a system prompt for task planning and prioritization, and uses copilotkit_stream to stream responses from an OpenAI model with defined tools. This enables dynamic task management within the UI. ```python from crewai.flow.flow import Flow, start from litellm import completion from copilotkit.crewai import copilotkit_stream, CopilotKitState class PlannerFlow(Flow[CopilotKitState]): @start() async def chat(self): system_prompt = """You are a helpful assistant who helps with planning a project. When asked to add a task, detail it by segregating into smaller tasks. When prioritizing tasks, do the prioritization yourself. Use task IDs from CopilotReadables efficiently.""" response = await copilotkit_stream( completion( model="openai/gpt-4o", messages=[ {"role": "system", "content": system_prompt}, *self.state.messages ], tools=[*self.state.copilotkit.actions], parallel_tool_calls=False, stream=True ) ) message = response.choices[0].message self.state.messages.append(message) ``` -------------------------------- ### Research Agent Workflow with LangGraph in Python Source: https://context7.com/ag-ui-protocol/open-ag-ui-canvas/llms.txt Implements a multi-node graph for a research agent using LangGraph and Langchain. It defines tools for searching and writing reports, and orchestrates 'chat_node' and 'search_node' to process research questions. Dependencies include langchain-openai, langgraph, and copilotkit. ```python import asyncio from typing import List, cast from langchain_openai import ChatOpenAI from langgraph.graph import StateGraph from langgraph.graph.message import add_messages from copilotkit.langgraph import copilotkit_emit_state, copilotkit_customize_config from langchain.tools import tool from langchain_core.messages import AIMessage, SystemMessage from langgraph.graph.graph import RunnableConfig # Placeholder for AgentState and Command, assuming they are defined elsewhere in the project. # For demonstration, we'll define minimal versions. class AgentState: def __init__(self, messages: List = None, report: str = "", resources: List = None, logs: List = None, research_question: str = ""): self.messages = messages if messages is not None else [] self.report = report self.resources = resources if resources is not None else [] self.logs = logs if logs is not None else [] self.research_question = research_question def get(self, key: str, default=None): return getattr(self, key, default) class Command: def __init__(self, goto: str, update: dict = None): self.goto = goto self.update = update if update is not None else {} async def async_tavily_search(query: str): # Placeholder for the actual search function await asyncio.sleep(0.1) # Simulate network latency return f"Results for {query}" @tool def Search(queries: List[str]): """A list of search queries to find resources for research.""" pass # Tool definition, execution is handled elsewhere @tool def WriteReport(report: str): """Write the research report.""" pass # Tool definition, execution is handled elsewhere async def chat_node(state: AgentState, config: RunnableConfig): config = copilotkit_customize_config(config, emit_intermediate_state=[ { "state_key": "report", "tool": "WriteReport", "tool_argument": "report", } ]) model = ChatOpenAI(temperature=0, model="gpt-4o-mini") response = await model.bind_tools([Search, WriteReport]).ainvoke([ SystemMessage(content=f"You are a research assistant. Research question: {state.get('research_question', '')} Current report: {state.get('report', '')} Available resources: {state['resources']}"), *state["messages"], ], config) ai_message = cast(AIMessage, response) if ai_message.tool_calls and ai_message.tool_calls[0]["name"] == "Search": return Command(goto="search_node", update={"messages": response}) return Command(goto="__end__", update={"messages": response}) async def search_node(state: AgentState, config: RunnableConfig): # Ensure state["messages"] is not empty and contains tool calls before accessing if not state["messages"] or not hasattr(state['messages'][-1], 'tool_calls') or not state['messages'][-1]['tool_calls']: # Handle cases where there are no tool calls or messages unexpectedly # This might involve returning an error, transitioning to another node, or logging # For now, we'll return the current state, but this should be handled more robustly. print("Warning: Unexpected state in search_node. No tool calls found.") return state queries = state["messages"][-1]["tool_calls" у][0]["args"]["queries"] for query in queries: state["logs"].append({"message": f"Search for {query}", "done": False}) await copilotkit_emit_state(config, state) tasks = [async_tavily_search(query) for query in queries] results = await asyncio.gather(*tasks, return_exceptions=True) for i, result in enumerate(results): state["logs"].append({"message": f"Result for query {i}: {result}", "done": True}) await copilotkit_emit_state(config, state) # Update state with results, typically adding them to messages or a specific state key # For this example, let's assume results are aggregated into state['resources'] or similar # A more complete implementation would parse and structure these results. state['resources'] = results # Simplified for example state['messages'].append(AIMessage(content=f"Search results obtained: {results}")) return state workflow = StateGraph(AgentState) workflow.add_node("chat_node", chat_node) workflow.add_node("search_node", search_node) workflow.set_entry_point("chat_node") workflow.add_edge("search_node", "chat_node") # Compile the graph graph = workflow.compile() ``` -------------------------------- ### Haiku Generation Tools with Zod Schema Source: https://context7.com/ag-ui-protocol/open-ag-ui-canvas/llms.txt TypeScript implementation of custom tools for haiku generation using Mastra and Zod. It includes a tool for extracting haiku topics and another for generating haikus with predefined image selections. Input and output schemas are defined using Zod. ```typescript // src/mastra/tools/index.ts import { createTool } from "@mastra/core/tools"; import { z } from "zod"; const images = [ "Mount_Fuji_Lake_Reflection_Cherry_Blossoms_Sakura_Spring.jpg", "Cherry_Blossoms_Sakura_Night_View_City_Lights_Japan.jpg", "Senso-ji_Temple_Asakusa_Cherry_Blossoms_Kimono_Umbrella.jpg" ]; export const haikuTopicTool = createTool({ id: "haikuTopicTool", description: "Extract the Haiku topic from user's message", inputSchema: z.object({ topic: z.string() }), outputSchema: z.string(), execute: async ({ context: { topic } }) => { console.log("Creating haiku about", topic); return topic; }, }); export const haikuGenerateTool = createTool({ id: "haikuGenerateTool", description: `Generate a haiku about a given topic. Always generate 3 images. Use only this list of images: ${images}`, inputSchema: z.object({ japanese: z.array(z.string()), english: z.array(z.string()), image_names: z.array(z.string()), }), outputSchema: z.object({ japanese: z.array(z.string()), english: z.array(z.string()), image_names: z.array(z.string()), }), execute: async ({ context: { japanese, english, image_names } }) => { return { japanese, english, image_names }; }, }); ``` -------------------------------- ### FastAPI Agent Server Source: https://context7.com/ag-ui-protocol/open-ag-ui-canvas/llms.txt The Python backend built with FastAPI exposes AI agents, including those powered by LangGraph and CrewAI, through a unified API. It utilizes the CopilotKit SDK to manage agent interactions and tool usage. ```APIDOC ## POST /copilotkit ### Description This endpoint serves as the primary interface for interacting with the AI agents managed by the FastAPI backend. It accepts requests and routes them to the appropriate agent (LangGraph or CrewAI) based on the SDK's configuration. ### Method POST ### Endpoint /copilotkit ### Parameters #### Path Parameters (None) #### Query Parameters (None) #### Request Body (The request body is expected to be in a format compatible with the CopilotKit SDK, typically containing user input and context for the agents.) ### Request Example (Example request body depends on the CopilotKit SDK and agent configurations) ### Response #### Success Response (200) (The response will be a JSON object containing the output or actions from the selected AI agent, as processed by the CopilotKit SDK.) #### Response Example (Example response body depends on the CopilotKit SDK and agent configurations) ## GET / ### Description A simple root endpoint to check if the FastAPI server is running. ### Method GET ### Endpoint / ### Parameters (None) ### Request Example GET / ### Response #### Success Response (200) - **message** (string) - A greeting message indicating the server is active. #### Response Example { "message": "Hello, World!" } ``` -------------------------------- ### Haiku Generation Agent with Mastra Source: https://context7.com/ag-ui-protocol/open-ag-ui-canvas/llms.txt TypeScript implementation of a Haiku generation agent using Mastra. It defines an agent that uses OpenAI with custom tools for topic extraction and haiku generation. The agent is instructed to use provided images and call a render_haiku tool. ```typescript // src/mastra/agents/index.ts import { openai } from "@ai-sdk/openai"; import { Agent } from "@mastra/core/agent"; import { haikuTopicTool, haikuGenerateTool } from "../tools"; export const haikuAgent = new Agent({ name: "Haiku Agent", tools: { haikuTopicTool, haikuGenerateTool }, model: openai("gpt-4o"), instructions: `You are skilled in haiku generation. Given a topic, generate a haiku about it. Use only provided images while generating images for a haiku. Call the render_haiku tool to display the haiku. If rejected, prompt user to generate a new haiku.`, }); ``` -------------------------------- ### CopilotKit Integration Endpoint Source: https://context7.com/ag-ui-protocol/open-ag-ui-canvas/llms.txt This Next.js API route serves as the connection point between the frontend components and the AI agents via the CopilotKit runtime. It handles requests and routes them to the appropriate agent logic, including specific handling for Mastra integration. ```APIDOC ## POST /api/copilotkit ### Description This endpoint integrates with CopilotKit to connect frontend applications with AI agents. It supports dynamic routing based on query parameters, including a specific path for Mastra client interactions. ### Method POST ### Endpoint /api/copilotkit ### Query Parameters - **isMastra** (boolean) - Optional - If present, indicates that the request should be handled by the Mastra integration logic. ### Request Body (No specific request body defined in the provided code, as it's handled by the CopilotKit runtime) ### Request Example (Example request body depends on the CopilotKit runtime configuration) ### Response #### Success Response (200) (Response is managed by the CopilotKit runtime, typically a JSON object representing agent output or interaction status) #### Response Example (Example response body depends on the CopilotKit runtime configuration) ``` -------------------------------- ### Next.js CopilotKit Integration Endpoint Source: https://context7.com/ag-ui-protocol/open-ag-ui-canvas/llms.txt This Next.js API route serves as the integration point for CopilotKit, connecting the frontend to AI agents. It handles requests and can conditionally use a Mastra client for specific agent interactions, forwarding requests to the CopilotKit runtime. Dependencies include '@copilotkit/runtime' and 'next'. ```typescript //app/api/copilotkit/route.ts import { CopilotRuntime, OpenAIAdapter, copilotRuntimeNextJSAppRouterEndpoint } from "@copilotkit/runtime"; import { NextRequest } from "next/server"; import { MastraClient } from "@mastra/client-js"; const serviceAdapter = new OpenAIAdapter(); const runtime = new CopilotRuntime({ remoteEndpoints: [ { url: process.env.REMOTE_ACTION_URL || "http://0.0.0.0:8000/copilotkit" } ] }); export const POST = async (req: NextRequest) => { if (req.nextUrl.searchParams.get("isMastra")) { const baseUrl = process.env.NEXT_PUBLIC_REMOTE_ACTION_URL_MASTRA || "http://localhost:4111"; const mastra = new MastraClient({ baseUrl }); const mastraAgents = await mastra.getAGUI({ resourceId: "TEST" }); const runtime = new CopilotRuntime({ agents: mastraAgents }); const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({ runtime, serviceAdapter, endpoint: "/api/copilotkit", }); return handleRequest(req); } else { const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({ runtime, serviceAdapter, endpoint: "/api/copilotkit", }); return handleRequest(req); } }; ``` -------------------------------- ### React CrewAI Planner Agent Remote Actions Source: https://context7.com/ag-ui-protocol/open-ag-ui-canvas/llms.txt A React component providing remote actions for a CrewAI agent to modify project tasks. It uses `useCopilotAction` to define an `addTask` function, allowing the agent to add tasks with specified priorities. The `useCopilotReadable` hook exposes the current tasks for the agent to read. Dependencies include `@copilotkit/react-core` and `uuid`. ```typescript // components/workspaces/planner-workspace.tsx import { useCopilotAction, useCopilotReadable } from "@copilotkit/react-core"; import { v4 as uuidv4 } from 'uuid'; export function PlannerWorkspace({ isAgentActive, setIsAgentActive }) { const [tasks, setTasks] = useState([{ projectName: "Launch MVP", isSelected: true, due: moment(new Date()).format("MMM D, YYYY"), teamCount: 3, tasks: [ { id: uuidv4(), title: "Define project scope", completed: true, priority: "High", assignee: "You" } ] }]); useCopilotReadable({ description: "All tasks in the project plan", value: JSON.stringify(tasks.find(p => p.isSelected)?.tasks), available: "enabled" }); useCopilotAction({ name: "addTask", available: "remote", description: "Add new tasks to the project plan", parameters: [{ name: "items", type: "object[]", attributes: [ { name: "task", type: "string", description: "Task to add" }, { name: "priority", type: "string", description: "Task priority", enum: ["High", "Medium", "Low"] } ] }], handler({ items }: { items: { task: string, priority: string }[] }) { const newTasks = items.map(item => ({ id: uuidv4(), title: item.task, priority: item.priority, assignee: "Agent", completed: false })); setTasks(tasks.map(project => project.isSelected ? { ...project, tasks: [...project.tasks, ...newTasks] } : project )); } }); return
{ setEditing({ type: 'japanese', index: lineIndex }); setEditValue(line); }}>{line}
)}