# Integrate Mastra in your Astro project In this guide, you'll build a tool-calling AI agent using Mastra, then connect it to Astro by importing and calling the agent directly from your routes. You'll use [AI SDK UI](https://ai-sdk.dev/docs/ai-sdk-ui/overview) and [AI Elements](https://ai-sdk.dev/elements) to create a beautiful, interactive chat experience. > **Note:** While this guide shows you how to use Astro with React and full server-side rendering (SSR), there are many ways to use Astro with Mastra. You can [opt-in to SSR](https://docs.astro.build/en/guides/on-demand-rendering/#enabling-on-demand-rendering) on a per-file basis and use other frameworks like Svelte, Vue, Solid, or Preact. You can use Astro to build out a chat interface and call endpoints [natively in Astro](https://docs.astro.build/en/recipes/call-endpoints/). ## Before you begin - You'll need an API key from a supported [model provider](https://mastra.ai/models). If you don't have a preference, use [OpenAI](https://mastra.ai/models/providers/openai). - Install Node.js `v22.13.0` or later ## Create a new Astro app (optional) If you already have an Astro app, skip to the next step. Your Astro app should be setup like this: - Use SSR (`output: "server"` in `astro.config.mjs`) - Use the [React integration](https://docs.astro.build/en/guides/integrations-guide/react/) - Tailwind installed To support [on-demand rendering](https://docs.astro.build/en/guides/on-demand-rendering/) this guide will use the [Node.js adapter](https://docs.astro.build/en/guides/integrations-guide/node/) but any of the supported server adapters will work. **npm**: ```bash npm create astro@latest mastra-astro -- --add node --add react --add tailwind --install --skip-houston --template minimal --git ``` **pnpm**: ```bash pnpm create astro mastra-astro --add node --add react --add tailwind --install --skip-houston --template minimal --git ``` **Yarn**: ```bash yarn create astro mastra-astro --add node --add react --add tailwind --install --skip-houston --template minimal --git ``` **Bun**: ```bash bunx create-astro mastra-astro --add node --add react --add tailwind --install --skip-houston --template minimal --git ``` This creates a project called `mastra-astro`, but you can replace it with any name you want. `cd` into your project and edit the `astro.config.mjs` file to set the [`output` setting](https://docs.astro.build/en/reference/configuration-reference/#output) to `"server"`: ```js // @ts-check import { defineConfig } from 'astro/config'; import node from '@astrojs/node'; import react from '@astrojs/react'; import tailwindcss from '@tailwindcss/vite'; // https://astro.build/config export default defineConfig({ output: 'server', adapter: node({ mode: 'standalone' }), integrations: [react()], vite: { plugins: [tailwindcss()] } }); ``` Lastly, edit the `tsconfig.json` to resolve paths: ```ts { "compilerOptions": { // ... "baseUrl": ".", "paths": { "@/*": [ "./src/*" ] } // ... } } ``` ## Initialize Mastra Run [`mastra init`](https://mastra.ai/reference/cli/mastra). When prompted, choose a provider (e.g. OpenAI) and enter your key: **npm**: ```bash npx mastra@latest init ``` **pnpm**: ```bash pnpm dlx mastra@latest init ``` **Yarn**: ```bash yarn dlx mastra@latest init ``` **Bun**: ```bash bun x mastra@latest init ``` This creates a `src/mastra` folder with an example weather agent and the following files: - `index.ts` - Mastra config, including memory - `tools/weather-tool.ts` - a tool to fetch weather for a given location - `agents/weather-agent.ts`- a weather agent with a prompt that uses the tool You'll call `weather-agent.ts` from your Astro routes in the next steps. ## Install AI SDK UI & AI Elements Install AI SDK UI along with the Mastra adapter: **npm**: ```bash npm install @mastra/ai-sdk@latest @ai-sdk/react ai ``` **pnpm**: ```bash pnpm add @mastra/ai-sdk@latest @ai-sdk/react ai ``` **Yarn**: ```bash yarn add @mastra/ai-sdk@latest @ai-sdk/react ai ``` **Bun**: ```bash bun add @mastra/ai-sdk@latest @ai-sdk/react ai ``` Next, initialize AI Elements. When prompted, choose the default options: **npm**: ```bash npx ai-elements@latest ``` **pnpm**: ```bash pnpm dlx ai-elements@latest ``` **Yarn**: ```bash yarn dlx ai-elements@latest ``` **Bun**: ```bash bun x ai-elements@latest ``` This downloads the entire AI Elements UI component library into a `@/components/ai-elements` folder. ## Create a chat route Create `src/pages/api/chat.ts`: ```ts import type { APIRoute } from "astro"; import { handleChatStream } from '@mastra/ai-sdk'; import { toAISdkV5Messages } from '@mastra/ai-sdk/ui' import { createUIMessageStreamResponse } from 'ai'; import { mastra } from '@/mastra'; const THREAD_ID = 'example-user-id'; const RESOURCE_ID = 'weather-chat'; export const POST: APIRoute = async ({ request }) => { const params = await request.json(); const stream = await handleChatStream({ mastra, agentId: 'weather-agent', params: { ...params, memory: { ...params.memory, thread: THREAD_ID, resource: RESOURCE_ID, } } }) return createUIMessageStreamResponse({ stream }) } export const GET: APIRoute = async () => { const memory = await mastra.getAgentById('weather-agent').getMemory() let response = null try { response = await memory?.recall({ threadId: THREAD_ID, resourceId: RESOURCE_ID, }) } catch { console.log('No previous messages found.') } const uiMessages = toAISdkV5Messages(response?.messages || []); return Response.json(uiMessages) } ``` The `POST` route accepts a prompt and streams the agent's response back in AI SDK format, while the `GET` route fetches message history from memory so the UI can be hydrated when the client reloads. ## Create a chat component Create `src/components/chat.tsx`: ```tsx import '@/styles/global.css'; import { useEffect, useState } from 'react'; import { DefaultChatTransport, type ToolUIPart } from 'ai'; import { useChat } from '@ai-sdk/react'; import { PromptInput, PromptInputBody, PromptInputTextarea, } from '@/components/ai-elements/prompt-input'; import { Conversation, ConversationContent, ConversationScrollButton, } from '@/components/ai-elements/conversation'; import { Message, MessageContent, MessageResponse } from '@/components/ai-elements/message'; import { Tool, ToolHeader, ToolContent, ToolInput, ToolOutput, } from '@/components/ai-elements/tool'; function Chat() { const [input, setInput] = useState(''); const { messages, setMessages, sendMessage, status } = useChat({ transport: new DefaultChatTransport({ api: '/api/chat', }), }); useEffect(() => { const fetchMessages = async () => { const res = await fetch('/api/chat'); const data = await res.json(); setMessages([...data]); }; fetchMessages(); }, [setMessages]); const handleSubmit = async () => { if (!input.trim()) return; sendMessage({ text: input }); setInput(''); }; return (
{messages.map((message) => (
{message.parts?.map((part, i) => { if (part.type === 'text') { return ( {part.text} ); } if (part.type?.startsWith('tool-')) { return ( ); } return null; })}
))}
setInput(e.target.value)} className="md:leading-10" value={input} placeholder="Type your message..." disabled={status !== 'ready'} />
); } export default Chat; ``` This component connects [`useChat()`](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat) to the `api/chat` endpoint, sending prompts there and streaming the response back in chunks. It renders the response text using the [``](https://ai-sdk.dev/elements/components/message#messageresponse-) component, and shows any tool invocations with the [``](https://ai-sdk.dev/elements/components/tool) component. ## Render the chat component The last step is to render the chat component on your index page. Edit `src/pages/index.astro`: ```html --- import Chat from '@/components/chat'; --- Astro ``` Import the `Chat` component and add it to the body with the `client:load` [directive](https://docs.astro.build/en/reference/directives-reference/#client-directives) so it runs on the client side. ## Test your agent 1. Run your Astro app with `npm run dev` 2. Open the chat at 3. Try asking about the weather. If your API key is set up correctly, you'll get a response ## Next steps Congratulations on building your Mastra agent with Astro! 🎉 From here, you can extend the project with your own tools and logic: - Learn more about [agents](https://mastra.ai/docs/agents/overview) - Give your agent its own [tools](https://mastra.ai/docs/agents/using-tools) - Add human-like [memory](https://mastra.ai/docs/agents/agent-memory) to your agent When you're ready, read more about how Mastra integrates with AI SDK UI and how to deploy your agent anywhere: - Integrate Mastra with [AI SDK UI](https://mastra.ai/guides/build-your-ui/ai-sdk-ui) - Deploy your agent [anywhere](https://mastra.ai/docs/deployment/overview)