Adding Custom Server Plugins to Agent-Native's /_agent-native/ Route
Create a TypeScript file in server/plugins/ that exports a default defineNitroPlugin function to register new HTTP handlers under the /_agent-native/ prefix.
Agent-Native (BuilderIO/agent-native) runs on Nitro, the server engine behind Nuxt 3. The /_agent-native/ API surface is constructed from Nitro plugins located in the server/plugins/ directory, which auto-load at server startup. Adding custom server plugins allows you to extend this API while reusing core utilities like authentication guards and database clients.
Where Core Endpoints Are Defined
The built-in /_agent-native/ routes are established by the core agent-chat plugin and imported by application templates.
Core Plugin Implementation
In packages/core/src/server/agent-chat-plugin.ts, the primary Nitro plugin registers handlers for routes including /agent-chat and /env-status. This file exports a default plugin using defineNitroPlugin that configures the router with the foundational API endpoints consumed by the Agent-Native UI.
Template-Level Integration
Application templates import this core functionality through files like templates/clips/server/plugins/agent-chat.ts. This re-exports the core plugin, making the /_agent-native/ endpoints available to specific template instances such as video or slide decks. The plugin loader also scans additional files in server/plugins/ automatically, as illustrated by templates/clips/server/plugins/_dev-upload-stub.ts.
Creating a Custom Server Plugin
Nitro automatically discovers and executes any TypeScript file in server/plugins/ that exports a default plugin definition.
File Structure and Boilerplate
Create a new file at server/plugins/my-custom-api.ts. The file must export a default function wrapped in defineNitroPlugin, which receives the Nitro instance containing the h3 router.
// server/plugins/my-custom-api.ts
import { defineNitroPlugin } from '@agent-native/core/server'
import { runAuthGuard } from '@agent-native/core/server/middleware/auth'
export default defineNitroPlugin((nitro) => {
const { router } = nitro
// Define your custom endpoint
router.get('/_agent-native/custom/status', async (event) => {
await runAuthGuard(event) // Enforces authentication
return { status: 'operational', timestamp: Date.now() }
})
})
Registering Routes with the Router
The router object is the underlying h3 instance used by all Agent-Native endpoints. Use standard methods like router.get(), router.post(), or router.use() to attach handlers. All paths must begin with /_agent-native/ to remain consistent with the public API surface and ensure compatibility with client-side helpers.
Securing Custom Endpoints
Protect your routes by importing the shared authentication utilities from the core package.
Using runAuthGuard
The runAuthGuard function, available from @agent-native/core/server/middleware/auth (as implemented in templates/clips/server/middleware/auth.ts), validates the session and throws a 401 error if the request lacks valid credentials. Apply it at the start of each handler to enforce consistent security with built-in endpoints.
import { runAuthGuard } from '@agent-native/core/server/middleware/auth'
router.post('/_agent-native/custom/data', async (event) => {
await runAuthGuard(event)
const body = await readBody(event)
// Process authenticated request
return { success: true }
})
Accessing Database and Request Utilities
Custom plugins can leverage the same infrastructure as core plugins by importing utilities from @agent-native/core/server.
Database Connections
Use createDbClient or access existing database pools initialized by the core plugin. Since custom plugins execute after the core plugin initializes in packages/core/src/server/agent-chat-plugin.ts, you can rely on established connections.
Request Helpers
Helpers like readBody, getQuery, and getSession are exported from the core server package. These provide typed access to request data and session context.
import { readBody, getSession } from '@agent-native/core/server'
router.get('/_agent-native/custom/user-profile', async (event) => {
await runAuthGuard(event)
const session = await getSession(event)
return { userId: session.userId }
})
Architecture and Execution Order
Nitro bundles all files from server/plugins/ into the server output and executes them sequentially during startup.
The execution flows as follows:
- The core plugin in
packages/core/src/server/agent-chat-plugin.tsinitializes first, setting up database pools and authentication context. - Template-specific plugins in
templates/*/server/plugins/load next. - Your custom plugins execute last, allowing you to depend on fully initialized core resources.
All plugins share the same router instance, meaning your custom /_agent-native/ routes mount alongside built-in ones without additional configuration.
Client-Side Integration
Consume your custom endpoints using the same client libraries provided by Agent-Native.
// Client-side component
import { useActionQuery } from '@agent-native/core/client'
const fetchStatus = () => useActionQuery('GET', '/_agent-native/custom/status')
The useActionQuery helper automatically handles base URL resolution and JSON parsing, treating your custom endpoints identically to native Agent-Native routes.
Summary
- Agent-Native's
/_agent-native/API is constructed from Nitro plugins in theserver/plugins/directory. - Create custom plugins by exporting a default
defineNitroPluginfunction that registers routes on therouterobject. - Prefix all custom routes with
/_agent-native/to maintain API consistency. - Import
runAuthGuardfrom@agent-native/core/server/middleware/authto enforce authentication. - Reuse core utilities like
readBodyandgetSessionfrom@agent-native/core/serverfor typed request handling. - Plugins auto-load at startup with no manual registration required.
Frequently Asked Questions
Do custom plugins execute before or after the core agent-chat plugin?
Custom plugins execute after the core plugin. The core agent-chat-plugin.ts initializes first in packages/core/src/server/, establishing database connections and session handling that your custom code can safely depend on.
Can I use the existing database connection in my custom server plugin?
Yes. Since your plugin runs after the core initialization, you can import createDbClient from @agent-native/core/server and utilize existing connection pools. The core plugin handles the initial database setup, allowing custom routes to perform queries immediately.
What authentication mechanism protects custom routes under /_agent-native/?
Routes are protected using the runAuthGuard function imported from @agent-native/core/server/middleware/auth. This utility, defined in templates/clips/server/middleware/auth.ts, validates session tokens and throws 401 errors for unauthenticated requests, ensuring consistent security across all API endpoints.
Does Agent-Native require a server restart to load new plugin files?
Nitro automatically discovers new files in server/plugins/ during the build process. In development mode, the server may auto-reload, but a manual restart ensures a clean initialization order, particularly when adding dependencies that the core plugin must initialize before your custom code executes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →