Skip to content

Getting Started

Nuxt Agentic (free)

Add Markdown agents and typed tools to any Nuxt app with the MIT module.

Add an agent to an existing Nuxt app with @nuxtagentic/nuxt. It runs in one request and streams steps to the page; it does not store runs or require a database. It works on any Nitro preset.

Installing the Module

npx nuxi module add @nuxtagentic/nuxt

During the release candidate, install the next tag: npx nuxi module add @nuxtagentic/nuxt@next or pnpm add @nuxtagentic/nuxt@next.

Set the key for each provider you use:

.env
NUXT_AGENTIC_OPENAI_API_KEY=sk-...
NUXT_AGENTIC_ANTHROPIC_API_KEY=sk-ant-...
NUXT_AGENTIC_GOOGLE_API_KEY=...

Writing an Agent

The file name is the agent name. The first heading is its title, and the rest is its instructions:

server/agents/triage.md
---
provider: 'anthropic'
model: 'claude-sonnet-5-5'
tools: ['lookup_issue']
---

# Issue triage

Look up the issue, then reply with one label: bug, feature or question.
SettingValuesDefault
provideropenai, anthropic, google, mockanthropic
modelThe provider's model IDclaude-sonnet-5-5
toolsNames of tools from server/toolsnone
tool_choiceauto, required (call a tool first), noneauto

Giving the Agent a Tool

A tool is a typed function the model can call. This one looks up a GitHub issue:

server/tools/lookup-issue.ts
import { z } from 'zod'

export default defineAgentTool({
  name: 'lookup_issue',
  description: 'Find a GitHub issue by number.',
  input: z.object({ number: z.number().int() }),
  async handler({ number }, { signal }) {
    return $fetch(`https://api.github.com/repos/nuxt/nuxt/issues/${number}`, { signal })
  },
})

The model's arguments are validated against input before the handler runs. A thrown error goes back to the model, so it can retry or explain. Tools with approval: true never run in the free module; Pro adds the approval flow.

Running the Agent from a Page

useAgent() starts a run and streams its messages into the page:

app/pages/triage.vue
<script setup lang="ts">
const { run, stop, messages, status, error } = useAgent('triage')
const issue = ref('')
</script>

<template>
  <form @submit.prevent="run(issue)">
    <input
      v-model="issue"
      aria-label="Issue"
    />
    <button :disabled="status === 'running'">Triage</button>
    <button
      v-if="status === 'running'"
      type="button"
      @click="stop"
    >
      Stop
    </button>
  </form>
  <p v-if="error">{{ error }}</p>
  <p
    v-for="(message, index) in messages"
    :key="index"
  >
    {{ message.role }}: {{ message.role === 'tool' ? message.name : message.content }}
  </p>
</template>

useAgent('triage') accepts only agents that exist. It returns run(input), stop(), messages, status (idle, running, success, error, or stopped), and error.

The run endpoint POST /api/_agentic/run/:agent has no authentication. Protect it with server middleware, route rules or rate limiting before you expose agents that spend API credit.

Trying It without an API Key

Set provider: 'mock' in the agent. It answers Mock response: <input>, or follows a script sent with the input:

await run({
  mock: {
    turns: [{ calls: [{ name: 'lookup_issue', input: { number: 7 } }] }, { text: 'bug' }],
  },
})

Real providers never see mock, so a page can keep sending a demo script after you switch.

Examples

  • Issue triage: tools, duplicate search, and a tool that needs approval.
  • Page summarizer: a fetch tool limited to allowed hosts.
  • Daily digest: a Nitro scheduled task that runs an agent every morning.

The module README covers the stream format, the options, and the DevTools tab. Moving to Pro keeps your agents and tools; see Upgrading.

Nuxt Agentic Pro adds durable runs, tool approval, automations and integrations. Join Pro early access for founding pricing: 40% off the first year for the first 100 licenses.