Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 51 additions & 1 deletion apps/client-cli-example/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,51 @@
# AG-UI CLI
# AG-UI CLI Example

A command-line chat interface demonstrating the AG-UI client with a Mastra agent. This example shows how to build an interactive CLI application that streams agent responses and tool calls in real-time.

## Features

- Interactive chat loop with streaming responses
- Real-time tool call visualization (weather and browser tools)
- Message history persistence using LibSQL
- Built with `@ag-ui/client` and `@ag-ui/mastra`

## Prerequisites

- Node.js 22.13.0 or later
- OpenAI API key

## Setup

1. Install dependencies from the repository root:

```bash
pnpm install
```

2. Set your OpenAI API key:
```bash
export OPENAI_API_KEY=your_api_key_here
```

## Usage

Run the CLI:

```bash
pnpm start
```

Try these example prompts:

- "What's the weather in San Francisco?"
- "Browse https://example.com"

Press `Ctrl+D` to quit.

## How It Works

This example uses:

- **MastraAgent**: Wraps a Mastra agent with AG-UI protocol support
- **Event Handlers**: Streams text deltas, tool calls, and results to the console
- **Memory**: Persists conversation history in a local SQLite database
13 changes: 6 additions & 7 deletions apps/client-cli-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@
"@ag-ui/client": "workspace:*",
"@ag-ui/core": "workspace:*",
"@ag-ui/mastra": "workspace:*",
"@ai-sdk/openai": "1.3.22",
"@mastra/client-js": "0.10.18",
"@mastra/core": "0.12.1",
"@mastra/libsql": "0.12.0",
"@mastra/loggers": "0.10.5",
"@mastra/memory": "0.12.0",
"@mastra/client-js": "1.0.0-beta.5",
"@mastra/core": "1.0.0-beta.5",
"@mastra/libsql": "1.0.0-beta.2",
"@mastra/loggers": "1.0.0-beta.1",
"@mastra/memory": "1.0.0-beta.2",
"open": "^10.1.2",
"zod": "^3.22.4"
"zod": "^4.1.12"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
8 changes: 4 additions & 4 deletions apps/client-cli-example/src/agent.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { MastraAgent } from "@ag-ui/mastra";
import { Memory } from "@mastra/memory";
Expand All @@ -7,8 +6,9 @@ import { weatherTool } from "./tools/weather.tool";
import { browserTool } from "./tools/browser.tool";

export const agent = new MastraAgent({
// @ts-ignore
resourceId: "cliExample",
agent: new Agent({
id: "ag-ui-agent",
name: "AG-UI Agent",
instructions: `
You are a helpful assistant that runs a CLI application.
Expand All @@ -26,13 +26,13 @@ export const agent = new MastraAgent({
Use the browserTool to browse the web.

`,
model: openai("gpt-4o-mini"),
model: "openai/gpt-4o-mini",
tools: { weatherTool, browserTool },
memory: new Memory({
storage: new LibSQLStore({
id: "mastra-cli-example-db",
url: "file:./mastra.db",
}),
}),
}),
threadId: "1",
});
2 changes: 1 addition & 1 deletion apps/client-cli-example/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as readline from "readline";
import { agent } from "./agent";
import { randomUUID } from "@ag-ui/client";
import { agent } from "./agent";

const rl = readline.createInterface({
input: process.stdin,
Expand Down
6 changes: 3 additions & 3 deletions apps/client-cli-example/src/tools/browser.tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export const browserTool = createTool({
url: z.string().describe("URL to browse"),
}),
outputSchema: z.string(),
execute: async ({ context }) => {
open(context.url);
return `Browsed ${context.url}`;
execute: async (inputData) => {
open(inputData.url);
return `Browsed ${inputData.url}`;
},
});
4 changes: 2 additions & 2 deletions apps/client-cli-example/src/tools/weather.tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export const weatherTool = createTool({
conditions: z.string(),
location: z.string(),
}),
execute: async ({ context }) => {
return await getWeather(context.location);
execute: async (inputData) => {
return await getWeather(inputData.location);
},
});

Expand Down
3 changes: 3 additions & 0 deletions apps/dojo/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,6 @@ dist
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.vite/

# Mastra files
.mastra
17 changes: 9 additions & 8 deletions apps/dojo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@
"@copilotkit/runtime": "1.10.6",
"@copilotkit/runtime-client-gql": "1.10.6",
"@copilotkit/shared": "1.10.6",
"@copilotkitnext/agent": "0.0.19-alpha.0",
"@copilotkitnext/react": "0.0.19-alpha.0",
"@copilotkitnext/runtime": "0.0.19-alpha.0",
"@copilotkitnext/agent": "0.0.19-alpha.0",
"@mastra/client-js": "^0.15.2",
"@mastra/core": "^0.20.2",
"@mastra/dynamodb": "^0.15.6",
"@mastra/libsql": "^0.15.1",
"@mastra/loggers": "^0.10.15",
"@mastra/memory": "^0.15.6",
"@mastra/client-js": "1.0.0-beta.5",
"@mastra/core": "1.0.0-beta.5",
"@mastra/dynamodb": "1.0.0-beta.1",
"@mastra/libsql": "1.0.0-beta.2",
"@mastra/loggers": "1.0.0-beta.1",
"@mastra/memory": "1.0.0-beta.2",
"@mdx-js/loader": "^3.1.0",
"@mdx-js/mdx": "^3.1.0",
"@mdx-js/react": "^3.1.0",
Expand Down Expand Up @@ -79,7 +79,7 @@
"tailwindcss-animate": "^1.0.7",
"untruncate-json": "^0.0.1",
"uuid": "^11.1.0",
"zod": "^3.25.67"
"zod": "^4.1.12"
},
"peerDependencies": {
"@ag-ui/client": "workspace:*",
Expand All @@ -100,6 +100,7 @@
"concurrently": "^9.2.0",
"eslint": "^9",
"eslint-config-next": "15.2.1",
"mastra": "1.0.0-beta.4",
"tailwindcss": "^4",
"tsx": "^4.7.0",
"typescript": "^5",
Expand Down
5 changes: 2 additions & 3 deletions apps/dojo/src/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { ServerStarterAgent } from "@ag-ui/server-starter";
import { ServerStarterAllFeaturesAgent } from "@ag-ui/server-starter-all-features";
import { MastraClient } from "@mastra/client-js";
import { MastraAgent } from "@ag-ui/mastra";
import { VercelAISDKAgent } from "@ag-ui/vercel-ai-sdk";
import { openai } from "@ai-sdk/openai";
import { LangGraphAgent, LangGraphHttpAgent } from "@ag-ui/langgraph";
import { AgnoAgent } from "@ag-ui/agno";
import { LlamaIndexAgent } from "@ag-ui/llamaindex";
Expand Down Expand Up @@ -127,13 +125,14 @@ export const agentsIntegrations: AgentIntegrationConfig[] = [

return MastraAgent.getRemoteAgents({
mastraClient,
resourceId: "mastra-agent-remote",
});
},
},
{
id: "mastra-agent-local",
agents: async () => {
return MastraAgent.getLocalAgents({ mastra });
return MastraAgent.getLocalAgents({ mastra, resourceId: "mastra-agent-local" });
},
},
// Disabled until we can support Vercel AI SDK v5
Expand Down
31 changes: 18 additions & 13 deletions apps/dojo/src/mastra/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { Memory } from "@mastra/memory";
import { LibSQLStore } from "@mastra/libsql";
import { DynamoDBStore } from "@mastra/dynamodb";

import { createStep, createWorkflow, Mastra } from "@mastra/core";
import { createTool } from "@mastra/core";
import { Mastra } from "@mastra/core";
import { createTool } from "@mastra/core/tools";
import { z } from "zod";
import { weatherTool } from "./tools";

Expand All @@ -14,17 +12,22 @@ function getStorage(): LibSQLStore | DynamoDBStore {
return new DynamoDBStore({
name: "dynamodb",
config: {
id: "storage-dynamodb",
tableName: process.env.DYNAMODB_TABLE_NAME,
},
});
} else {
return new LibSQLStore({ url: "file::memory:" });
return new LibSQLStore({
id: "storage-memory",
url: ":memory:"
});
}
}

export const mastra = new Mastra({
agents: {
agentic_chat: new Agent({
id: 'agentic_chat',
name: "agentic_chat",
instructions: `
You are a helpful weather assistant that provides accurate weather information.
Expand All @@ -36,7 +39,7 @@ export const mastra = new Mastra({
- Include relevant details like humidity, wind conditions, and precipitation
- Keep responses concise but informative
`,
model: openai("gpt-4o"),
model: "openai/gpt-4o",
tools: { get_weather: weatherTool },
memory: new Memory({
storage: getStorage(),
Expand All @@ -51,7 +54,8 @@ export const mastra = new Mastra({
}),
}),
backend_tool_rendering: new Agent({
name: "Weather Agent",
id: "backend_tool_rendering",
name: "backend_tool_rendering",
instructions: `
You are a helpful weather assistant that provides accurate weather information.

Expand All @@ -64,13 +68,14 @@ export const mastra = new Mastra({

Use the weatherTool to fetch current weather data.
`,
model: openai("gpt-4o-mini"),
model: "openai/gpt-4o-mini",
tools: { get_weather: weatherTool },
memory: new Memory({
storage: getStorage(),
}),
}),
shared_state: new Agent({
id: "shared_state",
name: "shared_state",
instructions: `
You are a helpful assistant for creating recipes.
Expand All @@ -82,9 +87,9 @@ export const mastra = new Mastra({
4. 'ingredients' is always an array of objects with 'icon', 'name', and 'amount' fields
5. 'instructions' is always an array of strings

If you have just created or modified the recipe, just answer in one sentence what you did. dont describe the recipe, just say what you did. Do not mention "working memory", "memory", or "state" in your answer.
If you have just created or modified the recipe, just answer in one sentence what you did. Do not describe the recipe, just say what you did. Do not mention "working memory", "memory", or "state" in your answer.
`,
model: openai("gpt-4o"),
model: "openai/gpt-4o",
memory: new Memory({
storage: getStorage(),
options: {
Expand Down Expand Up @@ -131,19 +136,19 @@ export const mastra = new Mastra({
.describe(
"Entire list of instructions for the recipe, including the new instructions and the ones that are already there",
),
changes: z.string().describe("A description of the changes made to the recipe"),
}),
}),
},
},
}),
}),
tool_based_generative_ui: new Agent({
id: "tool_based_generative_ui",
name: "tool_based_generative_ui",
instructions: `
You are a helpful assistant for creating haikus.
`,
model: openai("gpt-4o"),
model: "openai/gpt-4o",
tools: {
generate_haiku: createTool({
id: "generate_haiku",
Expand All @@ -158,7 +163,7 @@ export const mastra = new Mastra({
.describe("An array of three lines of the haiku in English"),
}),
outputSchema: z.string(),
execute: async ({ context }) => {
execute: async () => {
return "Haiku generated.";
},
}),
Expand Down
4 changes: 2 additions & 2 deletions apps/dojo/src/mastra/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export const weatherTool = createTool({
conditions: z.string(),
city: z.string(),
}),
execute: async ({ context }) => {
return await getWeather(context.location);
execute: async (inputData) => {
return await getWeather(inputData.location);
},
});

Expand Down
6 changes: 6 additions & 0 deletions docs/quickstart/clients.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ import { Memory } from "@mastra/memory"
import { LibSQLStore } from "@mastra/libsql"

export const agent = new MastraAgent({
resourceId: "cliExample",
agent: new Agent({
id: "ag-ui-assistant",
name: "AG-UI Assistant",
instructions: `
You are a helpful AI assistant. Be friendly, conversational, and helpful.
Expand All @@ -151,6 +153,7 @@ export const agent = new MastraAgent({
model: openai("gpt-4o"),
memory: new Memory({
storage: new LibSQLStore({
id: "storage-memory",
url: "file:./assistant.db",
}),
}),
Expand Down Expand Up @@ -555,7 +558,9 @@ import { weatherTool } from "./tools/weather.tool"
import { browserTool } from "./tools/browser.tool"

export const agent = new MastraAgent({
resourceId: "cliExample",
agent: new Agent({
id: "ag-ui-assistant",
name: "AG-UI Assistant",
instructions: `
You are a helpful assistant with weather and web browsing capabilities.
Expand All @@ -574,6 +579,7 @@ export const agent = new MastraAgent({
tools: { weatherTool, browserTool }, // Add both tools
memory: new Memory({
storage: new LibSQLStore({
id: "storage-memory",
url: "file:./assistant.db",
}),
}),
Expand Down
1 change: 1 addition & 0 deletions integrations/mastra/typescript/examples/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OPENAI_API_KEY=""
Loading
Loading