# Best Practices for Using Agent-Native: Building Agent-First Applications

> Discover best practices for Agent-Native, an open-source framework for building agent-first applications. Share data, actions, and runtime between AI agents and UIs using TypeScript and SQL.

- Repository: [Builder.io/agent-native](https://github.com/BuilderIO/agent-native)
- Tags: best-practices
- Published: 2026-06-21

---

**Agent-Native is an open-source framework that enables you to build agent-first applications where AI agents and user interfaces share the same data, actions, and runtime through reusable TypeScript actions and a unified SQL database.**

The BuilderIO/agent-native repository provides a complete architecture for creating collaborative applications where AI agents act as first-class teammates rather than sidecar features. By following these **best practices for using Agent-Native**, you ensure parity between human-driven UI interactions and agent-driven automation while maintaining type safety and a single source of truth across your entire stack.

## Define Work as Reusable Actions

Treat every piece of business logic as a **reusable action** declared once with a Zod schema and a `run` function. This pattern guarantees that the same function executes whether called from the UI, the agent, the CLI, or an external client.

In [`src/actions/send-email.ts`](https://github.com/BuilderIO/agent-native/blob/main/src/actions/send-email.ts), define the action using `defineAction` from `@agent-native/core`:

```ts
import { defineAction } from '@agent-native/core';
import { z } from 'zod';
import { db, replies } from '@/server/db';

export default defineAction({
  schema: z.object({
    emailId: z.string(),
    body: z.string(),
  }),
  // The same function runs from the UI, the agent, or the CLI
  run: async ({ emailId, body }) => {
    await db.insert(replies).values({ emailId, body });
  },
});

```

This approach, demonstrated in the repository's main README (lines 8-18), ensures that your business logic remains the single source of truth across all entry points.

## Centralize State in a Single SQL Database

Keep all application state in a **single SQL database** accessed through Drizzle-backed tables. Both the UI and the agent interact with this state through the same action surface, providing instant, real-time synchronization.

According to the "Everything syncs" section in the README (lines 30-33), this architecture makes collaborative editing trivial and eliminates data consistency issues between the frontend and AI runtime.

## Leverage the Built-In Skills System

**Skills** are plug-in modules that extend the agent runtime with capabilities like visual planning and automated recaps. Install them via the CLI and access them through slash commands in any chat-enabled UI.

Add a skill using the following command:

```bash
npx @agent-native/core@latest skills add visual-plan

```

After installation, type `/visual-plan` in your interface to generate structured plans with diagrams and file-by-file implementation maps. The skills system is documented in [`packages/skills/README.md`](https://github.com/BuilderIO/agent-native/blob/main/packages/skills/README.md) and referenced in the README (lines 30-31), providing out-of-the-box functionality without additional code.

## Treat Actions as First-Class API Endpoints

Avoid writing raw REST handlers or custom Nitro routes. Instead, expose all functionality through `defineAction` and consume them using the generated type-safe helpers `useActionQuery` and `useActionMutation`.

From a React component in [`src/components/SendEmailForm.tsx`](https://github.com/BuilderIO/agent-native/blob/main/src/components/SendEmailForm.tsx):

```tsx
import { useActionMutation } from '@agent-native/core';
import sendEmail from '@/actions/send-email';

export default function SendEmailForm() {
  const { mutate, isLoading } = useActionMutation(sendEmail);

  const onSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const form = e.target as HTMLFormElement;
    mutate({
      emailId: form.email.value,
      body: form.body.value,
    });
  };

  return (
    <form onSubmit={onSubmit}>
      <input name="email" placeholder="Email ID" required />
      <textarea name="body" placeholder="Message" required />
      <button type="submit" disabled={isLoading}>Send</button>
    </form>
  );
}

```

As specified in the Architecture Contract ([`AGENTS.md`](https://github.com/BuilderIO/agent-native/blob/main/AGENTS.md)), this pattern keeps your codebase DRY, ensures TypeScript safety, and makes the agent automatically aware of all capabilities.

## Follow UI Component Standards

Build all UI components using **shadcn/ui** primitives and **Tabler icons** to guarantee visual consistency and accessibility across templates. The AGENTS.md "Frontend And UX" section mandates these standards to ensure that new features integrate seamlessly with existing interfaces.

## Maintain Type-Safe Code Quality

Write **TypeScript exclusively** for all new source files (`.ts` and `.tsx`). Run Prettier and linting on every change to maintain the formatting standards defined in the project's `.prettierrc` and avoid CI failures. This type-first philosophy improves developer ergonomics and catches errors early.

## Apply the Four-Area Checklist

When adding new features, verify updates across four critical areas: **UI, actions, skills, and application state**. This checklist, detailed in the `adding-a-feature` skill documentation (linked from [`AGENTS.md`](https://github.com/BuilderIO/agent-native/blob/main/AGENTS.md)), prevents "agent-only" or "UI-only" regressions and keeps the system in lock-step.

## Summary

- **Define reusable actions** with `defineAction` to create a single source of truth for business logic accessible by UI, agent, and CLI.
- **Centralize state** in Drizzle-backed SQL tables to enable real-time sync between the interface and AI agent.
- **Install skills** via `npx @agent-native/core@latest skills add` to extend agent capabilities without custom code.
- **Consume actions** through `useActionMutation` and `useActionQuery` rather than writing raw REST endpoints.
- **Use shadcn/ui** components and Tabler icons for consistent, accessible design.
- **Write TypeScript exclusively** and enforce Prettier formatting to maintain code quality.
- **Apply the four-area checklist** (UI, actions, skills, state) for every feature to prevent architectural drift.

## Frequently Asked Questions

### What makes Agent-Native different from traditional full-stack frameworks?

Agent-Native treats AI agents as first-class citizens rather than add-ons. Unlike traditional frameworks where backend logic and frontend state often diverge, Agent-Native enforces a shared action surface where `defineAction` creates business logic that both the UI and agent consume simultaneously. This eliminates the need to synchronize separate implementations for human and AI interactions.

### How do I share state between the UI and the AI agent?

Agent-Native uses a single SQL database (accessed via Drizzle) that both the UI and agent interact with through the same action layer. When an action updates a record via the `run` function, both interfaces reflect the change immediately because they query the same underlying tables. This architecture is described in the "Everything syncs" section of the README (lines 30-33).

### Can I add custom REST endpoints to an Agent-Native app?

While possible, the framework discourages raw REST handlers in favor of extending the action surface. Before adding a custom Nitro route in [`packages/frame/src/server.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/frame/src/server.ts), search for an existing action to extend. This preference, documented in the Architecture Contract ([`AGENTS.md`](https://github.com/BuilderIO/agent-native/blob/main/AGENTS.md)), keeps security checks centralized and ensures the agent remains aware of all capabilities.

### What is the recommended way to extend agent capabilities?

Extend capabilities through the **skills system** rather than modifying core runtime code. Install official skills like `visual-plan` or `visual-recap` using the CLI command `npx @agent-native/core@latest skills add <skill>`. These plug-in modules register automatically with the runtime and expose slash commands in the chat interface, as implemented in [`packages/skills/src/index.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/skills/src/index.ts).