Agent-Native Runtime Architecture: How BuilderIO/agent-native Unifies UI, AI, and State
The Agent-Native runtime architecture synchronizes a React UI, AI agent, and backend through a shared SQL state layer, using a Run Manager to orchestrate long-running turns with durable background execution and real-time event streaming.
The BuilderIO/agent-native repository provides a framework for building AI-native applications where users and language models collaborate on the same state. The Agent-Native runtime architecture achieves this through a carefully designed system of primitives that manage actions, state persistence, and execution lifecycles across foreground and background environments.
Core Components of the Agent-Native Runtime
The runtime is built around a small set of primitives that manage actions, state, and long-running turns. Each component serves a specific responsibility in maintaining the unified state model.
Agent-Native UI
The Agent-Native UI is a React front-end located in applications under app/ that renders the chat interface, tool-specific UI components, and real-time presence indicators. According to packages/core/README.md, this layer communicates with the backend through the same action primitives that the AI agent uses, ensuring both human users and models operate on identical state.
Action Registry
The Action Registry declares server-side functions via defineAction in packages/core/src/action.ts. These functions are automatically exposed as:
- HTTP endpoints for UI interactions
- Agent tools with JSON Schema generated from Zod validation schemas
- CLI commands for development and automation
This unified exposure mechanism ensures that any business logic written once becomes available to all consumers of the Agent-Native runtime architecture.
Run Manager
Located in packages/core/src/agent/run-manager.ts, the Run Manager coordinates the lifecycle of agent executions. It handles:
- Starting runs via
startRun - Persisting events to the SQL database
- Managing soft-timeouts and heartbeats
- Handling auto-continuations for long-running operations
The Run Manager creates an in-memory ActiveRun instance for each execution while maintaining durable state in the database.
Production Agent
The Production Agent serves as the HTTP entry point at /api/agent-chat, implemented in packages/core/src/agent/production-agent.ts. This component:
- Validates incoming requests
- Resolves resource ownership
- Builds system prompts for the AI model
- Drives the main agent execution loop
- Handles background dispatch via
fireInternalDispatch
The Production Agent implements the Background-Aware Grace mechanism through resolveBackgroundDispatchOutcome, which waits 15 seconds for a background worker to claim the run before atomically claiming it in the foreground.
Durable Background and Self-Dispatch Worker
For operations exceeding the 40-second foreground soft-timeout, the architecture supports Durable Background execution through Netlify background functions (or similar platforms). As documented in packages/core/docs/design/durable-agent-runs.md, this system extends the execution budget to approximately 13 minutes (BACKGROUND_SOFT_TIMEOUT_CEILING_MS).
The Self-Dispatch / Worker mechanism operates as follows:
- The foreground handler inserts a run row into the database
- Fires an internal HMAC-signed dispatch to
/_agent-native/agent-chat/_process-run - The background worker claims the run via
claimBackgroundRun - Executes the full agent loop
- Streams events back through the SQL event log
If the background worker never claims the run, the foreground reclaims it atomically, guaranteeing exactly-one execution semantics.
SQL Event Log and State Layer
The SQL Event Log in packages/core/src/agent/run-store.ts stores every chat event in the agent_run_events table, including types: data, done, error, and auto_continue. Clients reconnect via /runs/:id/events?after=N, which polls against this table for real-time updates.
The State Layer uses a single Drizzle-compatible SQL database to hold:
- Application state
- Agent memory
- Action results
- Run metadata
This shared database approach enables instant synchronization and multi-user collaboration, as all parties read and write the same rows.
Data Flow in the Agent-Native Runtime
The execution flow follows a precise sequence to maintain consistency across the distributed components:
- Client initiates a POST request to
/api/agent-chatfrom the React front-end - Production Agent validates the request, resolves the owner, builds the system prompt, and calls
startRun - Run Manager inserts a
runrow, creates an in-memoryActiveRun, and begins streaming Server-Sent Events (SSE) to the client - Conditional dispatch: If
AGENT_CHAT_DURABLE_BACKGROUNDis enabled, the handler fires an internal dispatch to the background route - Background execution: The worker at
_process-runclaims the run and executes the full agent loop, writing each event toagent_run_events - Client streaming: The client receives events either from the in-memory stream (foreground) or via SQL-polling stream (
subscribeFromSQL) - Completion: When the turn finishes, the run status updates to
completedorerrored, the heartbeat stops, and the in-memory run cleans up after a delay
Defining Actions in Agent-Native
Actions represent the fundamental unit of work in the Agent-Native runtime architecture. The defineAction function in packages/core/src/action.ts bridges the gap between UI components and AI capabilities.
// packages/core/src/actions/email.ts
import { defineAction } from "@builder.io/agent-native/core";
export default defineAction({
// Zod schema is compiled to JSON-Schema for the agent tool surface
schema: z.object({
emailId: z.string(),
body: z.string(),
}),
// The function runs once per turn (or per auto-continue chunk)
run: async ({ emailId, body }) => {
await db.insert(replies).values({ emailId, body });
},
});
Once defined, the action becomes automatically available:
- To the UI as a button triggering
POST /api/email - To the agent as a tool named
emailwith the compiled JSON Schema
When the agent invokes this tool, the Run Manager persists the tool-call and done events, and the UI receives updates instantly through the shared SQL state layer.
Durable Background Execution
Long-running operations require special handling to avoid foreground timeout limits. The Agent-Native runtime architecture supports extended execution through background functions.
import { startRun } from "@builder.io/agent-native/core";
async function runLongTask(send, signal) {
// Example: batch insert 10,000 rows, checkpoint every 1,000
for (let i = 0; i < 10000 && !signal.aborted; i++) {
await db.insert(items).values({ id: i });
if (i % 1000 === 0) send({ type: "progress", detail: `${i} rows` });
}
}
// In a production-agent handler (simplified)
const runId = generateRunId();
startRun(runId, threadId, runLongTask, undefined, {
backgroundFunction: true, // opt-in to the ~13min soft timeout
});
Setting backgroundFunction: true lifts the 40-second ceiling, allowing the worker to complete extensive operations within a Netlify background function or similar async execution environment.
Summary
The Agent-Native runtime architecture from BuilderIO/agent-native delivers several critical capabilities:
- Unified state management: All actions, UI changes, and agent tool calls read and write the same SQL rows, eliminating synchronization complexities
- Real-time collaboration: SSE and poll-based reconnection via
subscribeFromSQLenable multiple users to edit the same document simultaneously - Durable execution: Background functions extend the run budget to approximately 13 minutes while maintaining foreground safety with 40-second soft timeouts
- Exactly-one execution: The grace period and atomic claiming mechanism in
resolveBackgroundDispatchOutcomeensure runs complete precisely once, even when background workers fail
Frequently Asked Questions
How does the Agent-Native runtime handle long-running agent turns?
The runtime implements a durable background execution model where the Production Agent in packages/core/src/agent/production-agent.ts can dispatch long-running work to background functions. When backgroundFunction: true is passed to startRun, the system extends the soft-timeout ceiling from 40 seconds to approximately 13 minutes (BACKGROUND_SOFT_TIMEOUT_CEILING_MS), allowing complex operations to complete without interruption.
What happens if the background worker fails to claim a run?
The foreground handler implements a Background-Aware Grace mechanism through resolveBackgroundDispatchOutcome in packages/core/src/agent/run-manager.ts. It waits 15 seconds for the background worker to claim the run via claimBackgroundRun. If the worker never claims it, the foreground atomically reclaims the run and streams the turn inline, guaranteeing exactly-one execution regardless of background function availability.
How does the SQL event log enable real-time collaboration?
The agent_run_events table in packages/core/src/agent/run-store.ts serves as the single source of truth for all execution events. Clients reconnect via /runs/:id/events?after=N, polling for events after a specific sequence number. Because all UI instances and the agent read from the same database rows, changes made by one user instantly propagate to others, creating a collaborative environment where both humans and AI models operate on synchronized state.
What is the role of defineAction in the architecture?
The defineAction function in packages/core/src/action.ts serves as the central registry for executable capabilities. It transforms Zod schemas into JSON-Schema for agent consumption while simultaneously exposing the same function as HTTP endpoints for UI integration. This design ensures that business logic remains consistent across all interfaces, whether invoked by a human clicking a button or an AI model calling a tool during its reasoning loop.
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 →