Skip to main content
Prerequisites: A React app using Next.js 14+, Remix v2, React Router v7, or TanStack Start.

Step 1: Get Your Credentials

2

Create an App

Click New App and give it a name
3

Copy Credentials

Copy your App ID and create an API Key

Step 2: Install Packages

npm install modifywithai @ai-sdk/react ai
PackagePurpose
modifywithaiCore SDK with hooks, components, and framework handlers
@ai-sdk/reactReact hooks for AI chat (from Vercel AI SDK)
aiVercel AI SDK core utilities

Step 3: Add Environment Variables

.env
MWAI_API_KEY=your_api_key_here
Never expose your API key to the browser. The token endpoint keeps it server-side.

Step 4: Create the Token Endpoint

The token endpoint generates short-lived tokens for the assistant. Your API key stays on the server—the browser only receives ephemeral tokens.
Create app/api/mwai/token/route.ts:
import { createAssistantTokenHandler } from "modifywithai/nextjs"

export const POST = createAssistantTokenHandler({
    appId: "your_app_id",
    // apiKey defaults to process.env.MWAI_API_KEY
})
OptionTypeDefaultDescription
appIdstringRequiredYour app ID from the dashboard
apiKeystringprocess.env.MWAI_API_KEYYour API key
apiUrlstringhttps://api.modifywithai.comAPI endpoint
getEndUserId(request) => Promise<string | null>Auto-generateFunction to get user ID

Step 5: Create the Assistant Component

Create a component that uses the useAssistant hook. This is where you define what actions the agent can perform.
components/assistant.tsx
"use client" // Next.js only

import { useAssistant } from "modifywithai"

export function Assistant() {
    const assistant = useAssistant({
        availableActions: [
            {
                name: "createItem",
                description: "Create a new item in the list",
                options: {
                    title: {
                        type: "string",
                        description: "The item title",
                        required: true,
                    },
                },
            },
            {
                name: "deleteItem",
                description: "Delete an item from the list",
                options: {
                    id: {
                        type: "string",
                        description: "The item ID to delete",
                        required: true,
                    },
                },
                approvalRequired: true, // User must confirm
            },
        ],
        getContext: () => ({
            // Pass current app state so the agent knows what's on screen
            currentPage: "home",
            items: [], // Your actual items here
        }),
        onAction: (action) => {
            // Handle executed actions
            switch (action.name) {
                case "createItem":
                    console.log("Create item:", action.options.title)
                    break
                case "deleteItem":
                    console.log("Delete item:", action.options.id)
                    break
            }
        },
    })

    if (!assistant.isReady) {
        return <div>Loading assistant...</div>
    }

    return (
        <div>
            {/* Display messages */}
            <div>
                {assistant.messages.map((message) => (
                    <div key={message.id}>
                        <strong>{message.role}:</strong>
                        {message.parts.map((part, i) =>
                            part.type === "text" ? <span key={i}>{part.text}</span> : null
                        )}
                    </div>
                ))}
            </div>

            {/* Input form */}
            <form onSubmit={assistant.handleSubmit}>
                <input
                    value={assistant.input}
                    onChange={(e) => assistant.setInput(e.target.value)}
                    placeholder="Try: Create an item called Test"
                />
                <button type="submit" disabled={assistant.status === "streaming"}>
                    Send
                </button>
            </form>
        </div>
    )
}

Step 6: Add the Component to Your App

Import and render the assistant component on your page:
app/page.tsx
import { Assistant } from "@/components/assistant"

export default function Home() {
    return (
        <main>
            <h1>My App</h1>
            <Assistant />
        </main>
    )
}

Optional: Add User Authentication

If your app has user authentication, pass the user ID to track conversations per user:
app/api/mwai/token/route.ts
import { createAssistantTokenHandler } from "modifywithai/nextjs"
import { auth } from "@/lib/auth" // Your auth library

export const POST = createAssistantTokenHandler({
    appId: "your_app_id",
    getEndUserId: async (request) => {
        const session = await auth()
        return session?.user?.id ?? null
    },
})
If no getEndUserId is provided, an anonymous ID is auto-generated for each session.

Optional: Using Server Data

Pass server-fetched data to the assistant component:
app/dashboard/page.tsx
import { getProjects } from "@/lib/data"
import { Assistant } from "@/components/assistant"

export default async function DashboardPage() {
    const projects = await getProjects()
    return <Assistant initialProjects={projects} />
}
components/assistant.tsx
"use client"

import { useState } from "react"
import { useAssistant } from "modifywithai"

export function Assistant({ initialProjects }) {
    const [projects, setProjects] = useState(initialProjects)

    const assistant = useAssistant({
        availableActions: [...],
        getContext: () => ({
            projects: projects.map(p => ({ id: p.id, name: p.name })),
        }),
        onAction: handleAction,
    })
    // ...
}

Next Steps