Skip to content
Merged
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.17.2 ",
"@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.1",
"@mastra/core": "^1.0.4",
"@mastra/libsql": "^1.0.0",
"@mastra/loggers": "^1.0.0",
"@mastra/memory": "^1.0.0",
"open": "^10.1.2",
"zod": "^3.22.4"
"zod": "^4.3.6"
},
"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
15 changes: 8 additions & 7 deletions apps/dojo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@
"@copilotkitnext/react": "1.51.2",
"@copilotkitnext/runtime": "1.51.2",
"@langchain/openai": "1.0.0",
"@mastra/client-js": "^0.17.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.1",
"@mastra/core": "^1.0.4",
"@mastra/dynamodb": "^1.0.0",
"@mastra/libsql": "^1.0.0",
"@mastra/loggers": "^1.0.0",
"@mastra/memory": "^1.0.0",
"@mdx-js/loader": "^3.1.0",
"@mdx-js/mdx": "^3.1.0",
"@mdx-js/react": "^3.1.0",
Expand Down Expand Up @@ -81,7 +81,7 @@
"tailwindcss-animate": "^1.0.7",
"untruncate-json": "^0.0.1",
"uuid": "^11.1.0",
"zod": "^3.25.67"
"zod": "^4.3.6"
},
"peerDependencies": {
"@ag-ui/client": "workspace:*",
Expand All @@ -101,6 +101,7 @@
"concurrently": "^9.2.0",
"eslint": "^9",
"eslint-config-next": "16.0.7",
"mastra": "^1.0.1",
"tailwindcss": "^4",
"tsx": "^4.7.0",
"typescript": "^5",
Expand Down
2 changes: 2 additions & 0 deletions apps/dojo/src/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,14 @@ export const agentsIntegrations = {

return MastraAgent.getRemoteAgents({
mastraClient,
resourceId: "mastra-agent-remote"
}) as Promise<Record<"agentic_chat" | "backend_tool_rendering" | "human_in_the_loop" | "tool_based_generative_ui", AbstractAgent>>;
},

"mastra-agent-local": async () => {
return MastraAgent.getLocalAgents({
mastra,
resourceId: "mastra-agent-local"
}) as Record<"agentic_chat" | "backend_tool_rendering" | "human_in_the_loop" | "shared_state" | "tool_based_generative_ui", AbstractAgent>;
},

Expand Down
24 changes: 12 additions & 12 deletions apps/dojo/src/files.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions apps/dojo/src/mastra/agents/agentic-chat.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { Memory } from "@mastra/memory";
import { z } from "zod";
import { weatherTool } from "../tools";
import { getStorage } from "../storage";

export const agenticChatAgent = new Agent({
id: 'agentic_chat',
name: "agentic_chat",
instructions: `
You are a helpful weather assistant that provides accurate weather information.
Expand All @@ -17,7 +17,7 @@ export const agenticChatAgent = new Agent({
- 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 Down
6 changes: 3 additions & 3 deletions apps/dojo/src/mastra/agents/backend-tool-rendering.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { Memory } from "@mastra/memory";
import { weatherTool } from "../tools";
import { getStorage } from "../storage";

export const backendToolRenderingAgent = 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 @@ -18,7 +18,7 @@ export const backendToolRenderingAgent = new Agent({

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(),
Expand Down
6 changes: 3 additions & 3 deletions apps/dojo/src/mastra/agents/human-in-the-loop.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { Memory } from "@mastra/memory";
import { getStorage } from "../storage";

export const humanInTheLoopAgent = new Agent({
name: "Task Planning Agent",
id: 'human_in_the_loop',
name: "human_in_the_loop",
instructions: `
You are a helpful task planning assistant that helps users break down tasks into actionable steps.

Expand All @@ -22,7 +22,7 @@ export const humanInTheLoopAgent = new Agent({
- Keep steps concise but descriptive
- Make sure steps are in logical order
`,
model: openai("gpt-4o-mini"),
model: "openai/gpt-4o-mini",
memory: new Memory({
storage: getStorage(),
}),
Expand Down
7 changes: 3 additions & 4 deletions apps/dojo/src/mastra/agents/shared-state.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { Memory } from "@mastra/memory";
import { z } from "zod";
import { getStorage } from "../storage";

export const sharedStateAgent = new Agent({
id: 'shared_state',
name: "shared_state",
instructions: `
You are a helpful assistant for creating recipes.
Expand All @@ -16,9 +16,9 @@ export const sharedStateAgent = new Agent({
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 @@ -65,7 +65,6 @@ export const sharedStateAgent = new Agent({
.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"),
}),
}),
},
Expand Down
8 changes: 4 additions & 4 deletions apps/dojo/src/mastra/agents/tool-based-generative-ui.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { createTool } from "@mastra/core";
import { createTool } from "@mastra/core/tools";
import { z } from "zod";

export const toolBasedGenerativeUIAgent = 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 @@ -23,7 +23,7 @@ export const toolBasedGenerativeUIAgent = new Agent({
.describe("An array of three lines of the haiku in English"),
}),
outputSchema: z.string(),
execute: async ({ context }) => {
execute: async () => {
return "Haiku generated.";
},
}),
Expand Down
6 changes: 5 additions & 1 deletion apps/dojo/src/mastra/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ export 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:"
});
}
}
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
Loading
Loading