How to Expose Zod-Validated Actions to the Agent in Agent-Native

To expose Zod actions to the agent in Agent-Native, declare your action using defineAction, attach a Zod schema for input validation, and configure the publicAgent object with expose: true; the framework automatically registers the action in the Agent Action Registry at /_agent-native/actions for agent invocation.

BuilderIO/agent-native treats every server action as a first-class API that can be called by both the UI and the AI agent. When you expose Zod actions to the agent, the framework uses your schema as the single source of truth for validation, auto-generated editor interfaces, and structured tool descriptions. This pattern ensures that agents receive identical type guarantees as your frontend components.

The Three-Step Exposure Pattern

Step 1: Declare the Action with defineAction

Every action starts with the defineAction helper imported from @agent-native/core. This function registers the server-side endpoint and prepares the action for runtime discovery.

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

export default defineAction({
  name: "provider-api-request",
  description: "Make an arbitrary request to a third-party provider API.",
  // configuration continues...
})

Step 2: Attach the Zod Schema

Supply a schema property containing a Zod object definition. Agent-Native uses this schema for runtime input validation and to generate the editor UI in the Studio. The schema becomes the contract that both human users and AI agents must satisfy.

schema: z.object({
  provider: z.string().min(1),
  endpoint: z.string().min(1),
  method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
  query: z.record(z.string()).optional(),
  body: z.any().optional(),
}),

Step 3: Configure the publicAgent Block

Add the publicAgent configuration object to control agent visibility and permissions. This block determines whether the action appears in the agent's tool surface and what constraints apply.

publicAgent: {
  expose: true,        // Makes the action visible to the agent
  readOnly: false,     // false = agent may write (POST/PUT/DELETE)
  requiresAuth: true,  // true = caller must be authenticated
},

When publicAgent.expose is set to true, the action's metadata—including its name, description, Zod schema, and permission flags—is injected into the Agent Action Registry.

What Happens Under the Hood

During server startup, the runtime walks all registered actions and extracts the Zod schema to build a structured description containing type information, required fields, and defaults. According to the source code in packages/core/src/server/action-routes.ts, the framework checks the publicAgent flags for each action; if expose is enabled, that description is added to the registry served at /api/_agent-native/action-registry.

The agent queries this registry when planning workflows. When the agent invokes an exposed action, it calls the endpoint at /api/_agent-native/actions/<action-id> with a JSON payload. If the payload fails Zod validation, the server returns a 400 error with a ZodError object, which the agent surface translates into a clear validation message.

Complete Working Example

The following example from templates/slides/actions/provider-api-request.ts (lines 79-100) demonstrates a fully exposed action that allows the agent to make arbitrary HTTP requests to third-party APIs:

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

export default defineAction({
  name: "provider-api-request",
  description: "Make an arbitrary request to a third-party provider API.",
  
  schema: z.object({
    provider: z.string().min(1),
    endpoint: z.string().min(1),
    method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
    query: z.record(z.string()).optional(),
    body: z.any().optional(),
    headers: z.record(z.string()).optional(),
  }),

  publicAgent: {
    expose: true,
    readOnly: false,
    requiresAuth: true,
  },

  async run({ input, context }) {
    const { provider, endpoint, method, query, body, headers } = input
    // Implementation logic to execute the request...
    return { success: true, data: result }
  },
})

For a read-only example, see templates/plan/actions/visual-answer.ts (line 117), where publicAgent: { expose: true, readOnly: true } allows the agent to retrieve visual plan blocks without mutation permissions.

Handling Validation Errors

Because the Zod schema serves as the single validation layer, any malformed input is rejected before reaching your business logic. When the agent sends an invalid payload, the response follows this structure:

{
  "error": "ZodError",
  "details": [
    { "path": ["provider"], "message": "String must contain at least 1 character(s)" }
  ]
}

The agent surface automatically surfaces these validation messages, allowing the AI to correct its approach without manual intervention. This guarantees that both UI components and agent calls receive identical data integrity protections.

Summary

  • Register actions using defineAction from @agent-native/core to create server-side endpoints.
  • Validate inputs by supplying a Zod schema; this defines the contract for both UI and agent interactions.
  • Expose actions to the agent by setting publicAgent: { expose: true }, with optional readOnly and requiresAuth flags for fine-grained control.
  • Reference the implementation in packages/core/src/server/action-routes.ts to understand how the runtime builds the Agent Action Registry from your publicAgent metadata.

Frequently Asked Questions

What is the Agent Action Registry in agent-native?

The Agent Action Registry is an automatically generated endpoint at /api/_agent-native/action-registry that exposes metadata for all actions with publicAgent.expose: true. The agent queries this registry to discover available tools, their input schemas, and permission requirements before planning workflow steps.

Can I expose actions without Zod schemas?

No. Agent-Native requires a Zod schema for any action exposed to the agent. The schema serves as the single source of truth for input validation, type-safe editor generation, and agent tool descriptions. Without it, the framework cannot guarantee data integrity or generate the structured descriptions needed for agent planning.

How do I restrict an agent to read-only operations?

Set readOnly: true inside the publicAgent configuration object. According to the source code in templates/plan/actions/visual-answer.ts, this flag signals to the agent that the action only retrieves data and does not perform mutations, which affects how the agent planner sequences operations and manages state.

What happens if the agent sends invalid data to an exposed action?

The server validates the payload against your Zod schema before executing the run function. If validation fails, the endpoint returns a 400 status with a ZodError detailing the specific field violations. The agent receives this feedback and can retry with corrected parameters, ensuring robust error handling without exposing internal server logic.

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 →