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:

  1. The core plugin in packages/core/src/server/agent-chat-plugin.ts initializes first, setting up database pools and authentication context.
  2. Template-specific plugins in templates/*/server/plugins/ load next.
  3. 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 the server/plugins/ directory.
  • Create custom plugins by exporting a default defineNitroPlugin function that registers routes on the router object.
  • Prefix all custom routes with /_agent-native/ to maintain API consistency.
  • Import runAuthGuard from @agent-native/core/server/middleware/auth to enforce authentication.
  • Reuse core utilities like readBody and getSession from @agent-native/core/server for 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →