# What Is the Agent-Native API? A Unified Interface for UI, Server, and AI Agents

> Explore the agent-native API a unified interface for UI, server, and AI agents. Simplify operations with a single abstraction and Zod schema integration.

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

---

**The agent-native API is a type-safe, unified action system that lets front-end components, back-end servers, and AI agents invoke the same operations through a single `defineAction` abstraction registered with Zod schemas.**

The agent-native API (available in the BuilderIO/agent-native repository) eliminates the traditional divide between client-side React hooks and server-side API endpoints. By centralizing application logic into reusable actions, the framework ensures that an LLM-driven agent can execute the exact same code paths as your UI components, maintaining consistency across the entire stack.

## Core Concepts of the Agent-Native API

### Actions and `defineAction`

The foundation of the API is the **`defineAction`** helper exported from **@agent-native/core**. An action is a reusable operation that declares:

- A **description** for the LLM agent to understand its purpose
- A **Zod schema** that validates input arguments at runtime
- An **`http` flag** determining whether it runs client-side or on the Nitro server
- A **`run` implementation** containing the actual business logic

All actions reside in template-specific `actions/` folders (e.g., `templates/videos/actions/`) and are automatically registered through a Vite plugin during development.

### Execution Contexts

When **`http: true`** is set, the action is exposed at `/api/action/<name>` and executes on the server. When **`http: false`** (or omitted), the action runs in-process, allowing AI agents to invoke logic directly without network overhead.

### Application State Helpers

The API provides **`readAppState`** and **`writeAppState`** utilities (from `@agent-native/core/application-state`) for managing shared navigation and user settings. These helpers persist data to SQL via Drizzle and are safe to call from any action or React component.

### Client-Side Hooks

React components consume actions through **`useActionQuery`** and **`useActionMutation`** (located in `packages/core/src/client/`). These hooks wrap fetch calls to provide loading states, error handling, and TypeScript autocompletion without raw HTTP requests.

## How the Agent-Native API Works

1. **Define an Action** – Export `default defineAction({ … })` from a file in the `actions/` folder, specifying the Zod input schema and run function.

2. **Vite Plugin Scans** – The `action-types-plugin` (defined in [`packages/core/src/vite/action-types-plugin.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/vite/action-types-plugin.ts)) scans the source tree, extracts TypeScript signatures, and generates type definitions under `node_modules/.vite` so both server and client share identical types.

3. **Expose via HTTP (Optional)** – Actions marked with `http: true` become reachable at `/api/action/<name>`; otherwise they remain in-process only.

4. **Consume in UI** – Components import the generated hook wrappers. The hook handles serialization, fetch logic, and caching while preserving type safety.

5. **Agent Invocation** – The LLM uses the generated JSON schemas to select and invoke actions via the same `run` function, ensuring the AI never bypasses framework validation.

## Agent-Native API Code Examples

### Defining an Action with Schema Validation

In [`templates/videos/actions/update-composition.ts`](https://github.com/BuilderIO/agent-native/blob/main/templates/videos/actions/update-composition.ts), an action updates database records with strict input validation:

```typescript
import { defineAction } from "@agent-native/core";
import { z } from "zod";

export default defineAction({
  description: "Update a composition’s metadata",
  schema: z.object({
    compositionId: z.string(),
    title: z.string().optional(),
    description: z.string().optional(),
  }),
  http: true,                     // reachable via /api/action/update-composition
  run: async ({ compositionId, title, description }) => {
    // Example pseudo-code that updates the DB (actual DB layer omitted)
    await db.compositions.update(compositionId, { title, description });
    return { success: true };
  },
});

```

### Calling Actions from React Components

Components use `useActionMutation` to invoke the action with full TypeScript support:

```tsx
import { useActionMutation } from "@agent-native/core";
import updateComposition from "templates/videos/actions/update-composition";

export function CompositionEditor({ compId }: { compId: string }) {
  const { mutate, isLoading, error } = useActionMutation(updateComposition);

  const save = async (updates: { title?: string; description?: string }) => {
    await mutate({ compositionId: compId, ...updates });
  };

  return (
    <>
      {/* UI elements that call save() */}
      {isLoading && <p>Saving…</p>}
      {error && <p className="error">{error.message}</p>}
    </>
  );
}

```

### Direct Agent Invocation

On the server side, an LLM agent can bypass HTTP and call the action directly:

```typescript
// In an LLM-driven agent script (server side)
import updateComposition from "templates/videos/actions/update-composition";

await updateComposition.run({
  compositionId: "c123",
  title: "New Title",
});

```

### Managing Shared Application State

Access global navigation or settings from any context using the state helpers:

```typescript
import { readAppState, writeAppState } from "@agent-native/core/application-state";

export async function getCurrentView() {
  const navigation = await readAppState("navigation");
  return navigation?.view ?? "unknown";
}

```

## Implementation Details and Key Files

The agent-native API surface is constructed from several critical source files in the BuilderIO/agent-native repository:

- **[`templates/videos/actions/view-screen.ts`](https://github.com/BuilderIO/agent-native/blob/main/templates/videos/actions/view-screen.ts)** – Demonstrates the standard action pattern, including reading navigation state via `readAppState` and returning JSON responses.

- **[`packages/core/src/vite/action-types-plugin.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/vite/action-types-plugin.ts)** – The Vite plugin that scans action directories, generates TypeScript definitions, and wires actions into the runtime at build time.

- **[`packages/core/src/client/use-action-mutation.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/client/use-action-mutation.ts)** (generated) – Provides the `useActionMutation` hook that React components import to interact with server actions.

- **[`packages/core/src/shared/application-state.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/shared/application-state.ts)** – Exports `readAppState` and `writeAppState`, implementing the SQL-backed shared state layer using Drizzle.

- **[`templates/slides/actions/provider-api-request.ts`](https://github.com/BuilderIO/agent-native/blob/main/templates/slides/actions/provider-api-request.ts)** – Implements the Provider API wrapper that allows agents to call third-party endpoints through controlled action boundaries.

- **[`packages/core/src/index.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/index.ts)** – The public API entry point that re-exports `defineAction`, state utilities, and client hooks.

## Summary

- The **agent-native API** unifies front-end, back-end, and AI agent execution through a single `defineAction` abstraction.
- Actions use **Zod schemas** for runtime validation and TypeScript generation.
- The **`http` flag** determines whether an action executes on the Nitro server or in-process.
- **Vite plugin generation** ensures type safety across the entire stack without manual synchronization.
- **`useActionQuery`** and **`useActionMutation`** provide React hooks that eliminate raw fetch calls.
- **Application state helpers** (`readAppState`, `writeAppState`) offer a typed interface to shared SQL data accessible by both UI and agents.

## Frequently Asked Questions

### What is the difference between `http: true` and `http: false` actions?

When `http: true` is set in the action definition, the operation is exposed at `/api/action/<name>` and executes within the Nitro server environment, making it suitable for database mutations or secrets access. When `http: false` or omitted, the action runs in-process only, allowing AI agents to invoke logic directly without network latency or HTTP overhead.

### How does the agent-native API ensure type safety across the stack?

The `action-types-plugin` (located in [`packages/core/src/vite/action-types-plugin.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/vite/action-types-plugin.ts)) scans all `actions/` directories during development, extracts TypeScript signatures from the Zod schemas, and generates type definitions in `node_modules/.vite`. This ensures that React hooks, server routes, and agent scripts all reference identical interfaces, preventing runtime mismatches.

### Can the agent-native API integrate with external third-party services?

Yes. The framework includes generic wrapper actions such as `provider-api-request` and `provider-api-docs` (found in `templates/**/actions/provider-api-*.ts`) that allow AI agents to call external APIs through controlled action boundaries. These wrappers handle authentication and rate limiting while exposing a consistent interface to the rest of the application.

### Where is application state stored when using `readAppState` and `writeAppState`?

Application state is persisted in SQL via Drizzle ORM. The helpers defined in [`packages/core/src/shared/application-state.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/shared/application-state.ts) provide a typed abstraction over the database, ensuring that navigation data, user settings, and other shared state remain consistent whether accessed from a React component in the browser or an LLM agent on the server.