@agent-native/core 0.147.0 → 0.148.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +115 -68
  3. package/corpus/templates/analytics/DEVELOPING.md +50 -3
  4. package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
  5. package/corpus/templates/analytics/app/i18n/index.ts +14 -29
  6. package/corpus/templates/analytics/app/i18n-data.ts +10 -10
  7. package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
  8. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
  9. package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +197 -18
  10. package/corpus/templates/analytics/server/db/schema.ts +23 -0
  11. package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
  12. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
  13. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
  14. package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
  15. package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
  16. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
  17. package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
  18. package/corpus/templates/analytics/server/plugins/db.ts +42 -0
  19. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
  20. package/corpus/templates/assets/app/i18n/index.ts +14 -29
  21. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
  22. package/corpus/templates/brain/app/i18n/index.ts +14 -29
  23. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
  24. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  25. package/corpus/templates/chat/app/i18n/index.ts +14 -29
  26. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
  27. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
  28. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
  29. package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
  30. package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
  31. package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
  32. package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
  33. package/corpus/templates/clips/desktop/src/app.tsx +1 -1
  34. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
  35. package/corpus/templates/content/app/i18n/index.ts +14 -29
  36. package/corpus/templates/crm/app/i18n/index.ts +14 -29
  37. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
  38. package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
  39. package/corpus/templates/design/actions/import-code.ts +2 -43
  40. package/corpus/templates/design/app/i18n/index.ts +14 -29
  41. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
  42. package/corpus/templates/dispatch/app/i18n-data.ts +1 -1
  43. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
  44. package/corpus/templates/factory/AGENTS.md +40 -49
  45. package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
  46. package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
  47. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
  48. package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
  49. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
  50. package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
  51. package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
  52. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  53. package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
  54. package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
  55. package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
  56. package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
  57. package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
  58. package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
  59. package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
  60. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
  61. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
  62. package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
  63. package/corpus/templates/factory/app/routes/factory.tsx +95 -42
  64. package/corpus/templates/factory/server/db/schema.ts +37 -0
  65. package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
  66. package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
  67. package/corpus/templates/factory/server/triage/audit.ts +79 -0
  68. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
  69. package/corpus/templates/forms/app/i18n/index.ts +14 -29
  70. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
  71. package/corpus/templates/macros/app/i18n/index.ts +14 -29
  72. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
  73. package/corpus/templates/mail/app/i18n/index.ts +14 -29
  74. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
  75. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
  76. package/corpus/templates/plan/app/i18n/index.ts +14 -29
  77. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
  78. package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
  79. package/corpus/templates/slides/actions/import-code.ts +2 -43
  80. package/corpus/templates/slides/app/i18n/index.ts +14 -29
  81. package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
  82. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
  83. package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
  84. package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
  85. package/corpus/templates/tasks/app/i18n/index.ts +14 -29
  86. package/dist/agent/engine/ai-sdk-engine.js +2 -1
  87. package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
  88. package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
  89. package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
  90. package/dist/agent/engine/provider-endpoint-validation.js +26 -0
  91. package/dist/agent/engine/provider-env-vars.d.ts +1 -1
  92. package/dist/agent/engine/provider-env-vars.js +1 -1
  93. package/dist/agent/engine/registry.d.ts +8 -6
  94. package/dist/agent/engine/registry.js +37 -24
  95. package/dist/agent/tool-search.d.ts +1 -0
  96. package/dist/agent/tool-search.js +17 -1
  97. package/dist/automations/service.js +4 -10
  98. package/dist/brand-kit/brand-signals.d.ts +13 -0
  99. package/dist/brand-kit/brand-signals.js +15 -0
  100. package/dist/brand-kit/index.d.ts +2 -2
  101. package/dist/brand-kit/index.js +1 -1
  102. package/dist/cli/plan-blocks.d.ts +3 -18
  103. package/dist/cli/plan-blocks.js +2 -95
  104. package/dist/cli/plan-publish-store.d.ts +2 -61
  105. package/dist/cli/plan-publish-store.js +2 -127
  106. package/dist/cli/skills-content/connection.d.ts +1 -1
  107. package/dist/cli/skills-content/connection.js +1 -52
  108. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  109. package/dist/cli/skills-content/visual-recap-skill.js +1 -553
  110. package/dist/client/agent-engine-key.d.ts +14 -4
  111. package/dist/client/agent-engine-key.js +51 -5
  112. package/dist/client/agent-provider-catalog.d.ts +20 -0
  113. package/dist/client/agent-provider-catalog.js +100 -0
  114. package/dist/client/blocks/index.d.ts +1 -0
  115. package/dist/client/blocks/index.js +1 -0
  116. package/dist/client/blocks/library/diagram.js +1 -1
  117. package/dist/client/blocks/library/sanitize-html.js +66 -2
  118. package/dist/client/blocks/library/wireframe-kit.js +69 -0
  119. package/dist/client/chat/run-recovery.js +4 -48
  120. package/dist/client/chat-first/apps-rail.d.ts +1 -1
  121. package/dist/client/chat-first/apps-rail.js +4 -4
  122. package/dist/client/chat-first/copy.js +1 -0
  123. package/dist/client/chat-first/types.d.ts +1 -0
  124. package/dist/client/chat-first.js +4 -3
  125. package/dist/client/i18n.d.ts +14 -0
  126. package/dist/client/i18n.js +18 -0
  127. package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
  128. package/dist/client/settings/ProviderSetupForm.js +145 -0
  129. package/dist/client/settings/SettingsPanel.js +52 -49
  130. package/dist/client/settings/index.d.ts +2 -0
  131. package/dist/client/settings/index.js +2 -0
  132. package/dist/coding-tools/run-code.d.ts +5 -0
  133. package/dist/coding-tools/run-code.js +196 -36
  134. package/dist/coding-tools/tool-orchestration.d.ts +10 -0
  135. package/dist/coding-tools/tool-orchestration.js +107 -0
  136. package/dist/collab/routes.d.ts +1 -1
  137. package/dist/jobs/frontmatter.d.ts +9 -0
  138. package/dist/jobs/frontmatter.js +16 -0
  139. package/dist/jobs/scheduler.js +8 -8
  140. package/dist/jobs/tools.d.ts +1 -1
  141. package/dist/jobs/tools.js +2 -7
  142. package/dist/localization/default-messages.d.ts +20 -0
  143. package/dist/localization/default-messages.js +25 -5
  144. package/dist/notifications/routes.d.ts +3 -3
  145. package/dist/observability/routes.d.ts +2 -2
  146. package/dist/onboarding/app-profile.js +1 -1
  147. package/dist/progress/routes.d.ts +1 -1
  148. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  149. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  150. package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
  151. package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
  152. package/dist/server/agent-chat/run-code-tools.js +3 -1
  153. package/dist/server/agent-chat-plugin.js +6 -6
  154. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  155. package/dist/server/agent-engine-api-key-route.js +43 -12
  156. package/dist/server/agents-bundle.js +2 -1
  157. package/dist/server/auth.js +21 -5
  158. package/dist/server/credential-provider.js +1 -0
  159. package/dist/server/design-token-utils.d.ts +18 -0
  160. package/dist/server/design-token-utils.js +31 -0
  161. package/dist/server/onboarding-html.js +22 -2
  162. package/dist/server/realtime-token.d.ts +1 -1
  163. package/dist/styles/blocks.css +132 -0
  164. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  165. package/dist/templates/chat/app/i18n/index.ts +14 -29
  166. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  167. package/dist/templates/default/app/i18n/index.ts +14 -29
  168. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  169. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  170. package/dist/triggers/dispatcher.js +1 -8
  171. package/docs/content/actions.mdx +4 -1
  172. package/docs/content/agent-surfaces.mdx +8 -6
  173. package/docs/content/automations.mdx +1 -1
  174. package/docs/content/database.mdx +6 -1
  175. package/docs/content/docs-components.mdx +22 -14
  176. package/docs/content/drop-in-agent.mdx +1 -1
  177. package/docs/content/environment-variables.mdx +39 -38
  178. package/docs/content/getting-started-actions.mdx +5 -4
  179. package/docs/content/getting-started-pages.mdx +7 -6
  180. package/docs/content/getting-started.mdx +4 -3
  181. package/docs/content/notifications.mdx +6 -6
  182. package/docs/content/progress.mdx +5 -5
  183. package/docs/content/routing.mdx +3 -1
  184. package/docs/content/server-database.mdx +13 -4
  185. package/docs/content/server-overview.mdx +9 -9
  186. package/docs/content/server-plugins.mdx +10 -4
  187. package/docs/content/server-routes.mdx +7 -2
  188. package/docs/content/tracking.mdx +4 -4
  189. package/docs/content/what-is-agent-native.mdx +4 -4
  190. package/package.json +4 -4
  191. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  192. package/src/templates/chat/app/i18n/index.ts +14 -29
  193. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  194. package/src/templates/default/app/i18n/index.ts +14 -29
  195. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  196. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  197. package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
@@ -391,12 +391,15 @@ export default defineAction({
391
391
  description: "Create a lead in the CRM.",
392
392
  schema: z.object({ name: z.string(), company: z.string() }),
393
393
  run: async ({ name, company }, ctx) => {
394
+ if (!ctx?.userEmail) {
395
+ throw new Error("An authenticated user is required.");
396
+ }
394
397
  const db = getDb();
395
398
  await db.insert(schema.leads).values({
396
399
  id: crypto.randomUUID(),
397
400
  name,
398
401
  company,
399
- ownerEmail: ctx?.userEmail ?? "system",
402
+ ownerEmail: ctx.userEmail,
400
403
  });
401
404
  return { ok: true };
402
405
  },
@@ -10,7 +10,7 @@ A **surface** is the way users (or other systems) interact with your app: a chat
10
10
 
11
11
  ## How surfaces relate to each other
12
12
 
13
- The four main product shapes sit on a spectrum from most interactive to fully headless. What makes them composable is that the foundation stays the same throughout: the same actions, the same SQL database, and the same agent loop power every shape. Adding a new surface doesn't mean rewriting what's underneath — you're just adding a new way to reach the same operations.
13
+ The four main product shapes sit on a spectrum from most interactive to fully headless. What makes them composable is that they share the same actions and SQL-backed app state. Use the framework agent loop when a surface needs an agent. Adding a new surface doesn't mean rewriting what's underneath — you're adding a new way to reach the same operations.
14
14
 
15
15
  <Diagram id="doc-block-hvdxgh" title="The surface spectrum" summary={"One action surface, four product shapes, each adding UI without changing the operation underneath."}>
16
16
 
@@ -37,7 +37,9 @@ The four main product shapes sit on a spectrum from most interactive to fully he
37
37
  </div>
38
38
  </div>
39
39
  <div class="diagram-base" data-rough>
40
- <span class="diagram-muted">same actions · same SQL · same agent loop</span>
40
+ <span class="diagram-muted"
41
+ >same actions · SQL-backed state · agent loop where used</span
42
+ >
41
43
  </div>
42
44
  ```
43
45
 
@@ -192,7 +194,7 @@ Full apps add product UI around the same action and agent contract:
192
194
 
193
195
  ### SQL state
194
196
 
195
- App data, navigation, settings, and chat history are all durable. The agent reads and writes the same rows the UI does.
197
+ App data, navigation, settings, and chat history are durable in SQL. The agent reads and writes the same rows the UI does.
196
198
 
197
199
  ### Context awareness
198
200
 
@@ -200,7 +202,7 @@ The agent knows the current route, selection, and focused object, so "edit this"
200
202
 
201
203
  ### Live sync
202
204
 
203
- Agent changes update the UI in real time, and UI changes update the agent's context. No polling, no refresh.
205
+ Agent changes update the UI through live sync, and UI changes update the agent's context. The framework uses SSE with polling fallback, so users do not need to refresh manually.
204
206
 
205
207
  ### Deep links
206
208
 
@@ -224,9 +226,9 @@ want a complete product shape.
224
226
 
225
227
  Every Agent-Native app eventually needs a place where users can configure their agent: set standing instructions, review what it's done, connect MCP servers, manage automations, and control access. Building that UI from scratch is a lot of work. Agent-Native ships a pre-built full-page component, `AgentTabsPage`, that covers all of it across twelve tabs.
226
228
 
227
- Mount it at `/agent` in your app. Current templates pair that route with an app-navigation entry and pass `agentPageHref="/agent"` to `AgentSidebar`, so the sidebar's Resources and Settings modes can link to the full page without duplicating those flows.
229
+ Mount it at `/settings/agent` in your app. Current templates use this as the canonical route and pass `agentPageHref="/settings/agent"` to `AgentSidebar`. `/agent` is kept as a legacy redirect.
228
230
 
229
- ```tsx filename="app/routes/agent.tsx"
231
+ ```tsx filename="app/routes/settings.agent.tsx"
230
232
  import { AgentTabsPage } from "@agent-native/core/client/agent-chat";
231
233
  export default function AgentRoute() {
232
234
  return <AgentTabsPage />;
@@ -214,7 +214,7 @@ emit(
214
214
  customerEmail: "jane@example.com",
215
215
  total: 49.99,
216
216
  },
217
- { owner: "steve@builder.io" },
217
+ { owner: "user@example.com" },
218
218
  );
219
219
  ```
220
220
 
@@ -267,7 +267,12 @@ All database schema updates must be **strictly additive**.
267
267
 
268
268
  ### Safe Migration Path
269
269
 
270
- Instead of pushing directly, schema changes should be applied via SQL migrations executed at application startup. Implement additive migrations within a server plugin (e.g., `server/plugins/db.ts`) by invoking the framework's `runMigrations()` helper:
270
+ Instead of pushing directly, schema changes should be applied via additive SQL
271
+ migrations. For local development, implement them in a server plugin (e.g.
272
+ `server/plugins/db.ts`) by invoking the framework's `runMigrations()` helper.
273
+ For production or serverless deployments, run migrations in a release or deploy
274
+ step instead of on the first request. The Chat template provides
275
+ `pnpm migrate:production` for this.
271
276
 
272
277
  <AnnotatedCode
273
278
  id="doc-block-zaaj7e"
@@ -105,7 +105,7 @@ pnpm install
105
105
  pnpm dev
106
106
  ```
107
107
 
108
- Open `http://localhost:3000`. The app is ready when **VITE ready** appears in the terminal.
108
+ Open the local URL shown by the dev server. The app is ready when **VITE ready** appears in the terminal.
109
109
 
110
110
  ### Sign in
111
111
 
@@ -130,7 +130,7 @@ pnpm install
130
130
  pnpm dev
131
131
  ```
132
132
 
133
- Open `http://localhost:3000`. The app is ready when **VITE ready** appears in the terminal.
133
+ Open the local URL shown by the dev server. The app is ready when **VITE ready** appears in the terminal.
134
134
 
135
135
  ### Sign in
136
136
 
@@ -215,13 +215,13 @@ Use `Notice` when a `Callout` would be too easy to skim past — something the r
215
215
 
216
216
  <Banner
217
217
  tone="warning"
218
- body="This page describes the v9 API. See [Migrating to v10](/docs/migrating-v10) for what changed."
218
+ body="This page describes a beta API. Check the release notes before using it."
219
219
  />
220
220
 
221
221
  ```mdx
222
222
  <Banner
223
223
  tone="warning"
224
- body="This page describes the v9 API. See [Migrating to v10](/docs/migrating-v10) for what changed."
224
+ body="This page describes a beta API. Check the release notes before using it."
225
225
  />
226
226
  ```
227
227
 
@@ -377,13 +377,17 @@ Use a fenced code block with the `mermaid` language tag. Mermaid supports flowch
377
377
  note: "New action — callable from agent, UI, and CLI",
378
378
  },
379
379
  { path: "actions/list-text-analyses.ts", change: "added" },
380
- { path: "app/routes/analyses.tsx", change: "modified" },
380
+ { path: "app/routes/analyses.tsx", change: "added" },
381
381
  {
382
- path: "app/config/nav.ts",
383
- change: "modified",
384
- note: "Add the new route to the sidebar nav",
382
+ path: "server/db/schema.ts",
383
+ change: "added",
384
+ note: "Define the app-owned table",
385
+ },
386
+ {
387
+ path: "server/plugins/db.ts",
388
+ change: "added",
389
+ note: "Run additive migrations",
385
390
  },
386
- { path: "db/migrations/001_analyses.sql" },
387
391
  ]}
388
392
  />
389
393
 
@@ -397,13 +401,17 @@ Use a fenced code block with the `mermaid` language tag. Mermaid supports flowch
397
401
  note: "New action — callable from agent, UI, and CLI",
398
402
  },
399
403
  { path: "actions/list-text-analyses.ts", change: "added" },
400
- { path: "app/routes/analyses.tsx", change: "modified" },
404
+ { path: "app/routes/analyses.tsx", change: "added" },
401
405
  {
402
- path: "app/config/nav.ts",
403
- change: "modified",
404
- note: "Add the new route to the sidebar nav",
406
+ path: "server/db/schema.ts",
407
+ change: "added",
408
+ note: "Define the app-owned table",
409
+ },
410
+ {
411
+ path: "server/plugins/db.ts",
412
+ change: "added",
413
+ note: "Run additive migrations",
405
414
  },
406
- { path: "db/migrations/001_analyses.sql" },
407
415
  ]}
408
416
  />
409
417
  ```
@@ -170,7 +170,7 @@ export default function AgentRoute() {
170
170
  }
171
171
  ```
172
172
 
173
- `<AgentPanel>` gives you the raw tabs (Chat / CLI / Resources) without the sidebar wrapper, the collapse button, or any state persistence. Put it wherever you want; you handle the layout.
173
+ `<AgentPanel>` gives you the raw tabs (Chat / CLI / Resources) without the sidebar wrapper or the collapse button. Put it wherever you want; you control the surrounding layout.
174
174
 
175
175
  ### Selected props
176
176
 
@@ -24,44 +24,45 @@ deployment-specific values in the environment or scoped secret store.
24
24
 
25
25
  ## Common application and deployment variables
26
26
 
27
- | Variable | What it controls | Supported values or format |
28
- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
29
- | `DATABASE_URL` | Primary SQL connection. Local development falls back to SQLite when it is unset. Production also accepts `<APP_NAME>_DATABASE_URL` or Netlify's `NETLIFY_DATABASE_URL`. | A provider-specific SQL URL, or unset for local SQLite. |
30
- | `DATABASE_AUTH_TOKEN` | Separate database token when the database provider requires one. | An opaque provider token, or unset when the URL includes authentication. |
31
- | `APP_URL` | Optional canonical public origin used for auth, OAuth, A2A, webhooks, and generated links. Netlify and Vercel metadata are inferred when it is unset. | An absolute public `http(s)` origin. |
32
- | `BETTER_AUTH_URL` | Optional Better Auth origin override. Known template or request context, `APP_URL`, and platform metadata such as Netlify or Vercel are used when it is unset. | An absolute public `http(s)` origin. |
33
- | `APP_BASE_PATH` | Mounts an app under a path such as `/mail`. | Unset for a standalone app, or a slash-prefixed path. |
34
- | `PORT` | Local Node/Nitro server port. | A decimal TCP port. |
35
- | `NITRO_PRESET` | Build and deployment adapter. | A preset supported by the target host, such as `node`, `netlify`, `vercel`, or `cloudflare_pages`. |
36
- | `BETTER_AUTH_SECRET` | Stable Better Auth session signing secret for standalone production apps. Workspace deploys can derive it from `A2A_SECRET`. | A fresh random value of at least 32 characters. |
37
- | `OAUTH_STATE_SECRET` | Dedicated signing key for OAuth state envelopes. Falls back to `BETTER_AUTH_SECRET` when unset. | A fresh random value of at least 32 characters. |
38
- | `A2A_SECRET` | Shared HMAC for trusted cross-app A2A calls and signed handoffs. | One shared random value across trusted apps. |
39
- | `SECRETS_ENCRYPTION_KEY` | Legacy app-local/shared encryption fallback. | A stable encryption key; prefer the workspace key for new shared vaults. |
40
- | `WORKSPACE_SECRETS_ENCRYPTION_KEY` | Stable encryption key for a workspace-shared secrets vault. | The same stable key in every app that reads the vault. |
41
- | `WORKSPACE_SECRETS_ENCRYPTION_KEY_PREVIOUS` | Previous workspace key during rotation. | The old key only; remove it after migration. |
42
- | `ANTHROPIC_API_KEY` | Optional deploy-level fallback for the embedded production agent. | An API key; prefer scoped credentials for multi-tenant apps. |
43
- | `AGENT_ENGINE` | Explicitly selects the agent engine instead of auto-detecting from provider keys. | A registered engine name such as `anthropic`, `ai-sdk:openai`, `builder`, or `codex-cli`. |
44
- | `AGENT_ENGINE_PREFER_BYO_KEY` | Prefers a provider key you set over the managed Builder gateway during auto-detection. | `true` or `1`; Builder still applies as the fallback when no provider key is set. |
45
- | `AUTH_MODE` | Selects the local authentication behavior used by CLI and agent flows. | Unset or `local`; this is not a browser login bypass. |
46
- | `AUTH_DISABLED` | Disables auth for local or preview-only work. Unset already means false. | `true` or `1`; never use on a public production app. |
47
- | `AUTH_MAGIC_LINK` | Controls the password-first versus magic-link sign-in path. | `0` keeps password-first sign-in; otherwise a configured email transport can enable magic links. |
48
- | `AUTH_SKIP_EMAIL_VERIFICATION` | Skips signup email verification for local QA or previews. | `1`; never use it to weaken production auth. |
49
- | `ACCESS_TOKEN` / `ACCESS_TOKENS` | Static bearer fallback for MCP and Connect clients. | One token or a delimited token list; these are not browser auth. |
50
- | `AGENT_PROD_CODE_EXECUTION` | Production code-execution policy. | `off`, `sandboxed`, or `trusted`. See [Production Code Execution](/docs/deployment#production-code-execution). |
51
- | `AGENT_NATIVE_SSR_CACHE` | Deployment-wide public SSR shell cache policy. | Unset/`on`, `off`, or a duration such as `30s` or `5m`. See [SSR Caching](/docs/deployment#ssr-caching). |
52
- | `AGENT_NATIVE_DISABLE_KEEP_WARM` | Lets a scale-to-zero database autosuspend instead of being woken every minute. | `1`; see [Keep-warm](/docs/deployment#netlify-keep-warm). |
53
- | `AGENT_NATIVE_KEEP_WARM_SCHEDULE` | Keep-warm cadence override. | A 5-field cron expression such as `*/5 * * * *`; an unparseable value fails the build. |
54
- | `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND` | Drops only the background-function warm and keeps the server warm. | `1`; see [Keep-warm](/docs/deployment#netlify-keep-warm). |
55
- | `AGENT_NATIVE_DISABLE_INPROCESS_SWEEPS` | Turns off the in-process backstop sweep timers where a durable scheduler drives the same work. | `1`; queued work is not retried without another driver. |
56
- | `AGENT_NATIVE_SKIP_ENSURE_TABLES` | Skips on-demand schema DDL for an already-migrated database. | `1`; see [On-demand schema DDL](/docs/deployment#skip-ensure-tables). You own migrations when this is set. |
57
- | `COOKIE_DOMAIN` | Shares auth cookies across same-database subdomains when explicitly configured. | A cookie domain. |
58
- | `CORS_ALLOWED_ORIGINS` | Cross-origin request allowlist. | A comma-separated list of exact origins. |
59
- | `WEBHOOK_BASE_URL` | Optional public base URL for self-callback and webhook targets. | An absolute public `http(s)` origin. |
60
- | `APP_NAME` | App identity used by workspace and app-scoped configuration. | A short app name, such as `mail`. |
61
- | `APP_ID` / `APP_TEMPLATE` | Optional app identity and generated-template metadata. | App-owned strings. |
62
- | `NODE_ENV` | Node runtime mode. | Normally `development`, `test`, or `production`. |
63
- | `CI` | Marks CI-driven test and build behavior. | A CI-provided truthy value. |
64
- | `DEBUG` | Enables resolver-specific debug logging. | A resolver-supported truthy or namespace value. |
27
+ | Variable | What it controls | Supported values or format |
28
+ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
29
+ | `DATABASE_URL` | Primary SQL connection. Local development falls back to SQLite when it is unset. Production also accepts `<APP_NAME>_DATABASE_URL` or Netlify's `NETLIFY_DATABASE_URL`. | A provider-specific SQL URL, or unset for local SQLite. |
30
+ | `DATABASE_AUTH_TOKEN` | Separate database token when the database provider requires one. | An opaque provider token, or unset when the URL includes authentication. |
31
+ | `APP_URL` | Optional canonical public origin used for auth, OAuth, A2A, webhooks, and generated links. Netlify and Vercel metadata are inferred when it is unset. | An absolute public `http(s)` origin. |
32
+ | `BETTER_AUTH_URL` | Optional Better Auth origin override. Known template or request context, `APP_URL`, and platform metadata such as Netlify or Vercel are used when it is unset. | An absolute public `http(s)` origin. |
33
+ | `APP_BASE_PATH` | Mounts an app under a path such as `/mail`. | Unset for a standalone app, or a slash-prefixed path. |
34
+ | `PORT` | Local Node/Nitro server port. | A decimal TCP port. |
35
+ | `NITRO_PRESET` | Build and deployment adapter. | A preset supported by the target host, such as `node`, `netlify`, `vercel`, or `cloudflare_pages`. |
36
+ | `BETTER_AUTH_SECRET` | Stable Better Auth session signing secret for standalone production apps. Workspace deploys can derive it from `A2A_SECRET`. | A fresh random value of at least 32 characters. |
37
+ | `OAUTH_STATE_SECRET` | Dedicated signing key for OAuth state envelopes. Falls back to `BETTER_AUTH_SECRET` when unset. | A fresh random value of at least 32 characters. |
38
+ | `A2A_SECRET` | Shared HMAC for trusted cross-app A2A calls and signed handoffs. | One shared random value across trusted apps. |
39
+ | `SECRETS_ENCRYPTION_KEY` | Legacy app-local/shared encryption fallback. | A stable encryption key; prefer the workspace key for new shared vaults. |
40
+ | `WORKSPACE_SECRETS_ENCRYPTION_KEY` | Stable encryption key for a workspace-shared secrets vault. | The same stable key in every app that reads the vault. |
41
+ | `WORKSPACE_SECRETS_ENCRYPTION_KEY_PREVIOUS` | Previous workspace key during rotation. | The old key only; remove it after migration. |
42
+ | `ANTHROPIC_API_KEY` | Optional deploy-level fallback for the embedded production agent. | An API key; prefer scoped credentials for multi-tenant apps. |
43
+ | `AGENT_ENGINE` | Explicitly selects the agent engine instead of auto-detecting from provider keys. | A registered engine name such as `anthropic`, `ai-sdk:openai`, `builder`, or `codex-cli`. |
44
+ | `AGENT_ENGINE_PREFER_BYO_KEY` | Prefers a provider key you set over the managed Builder gateway during auto-detection. | `true` or `1`; Builder still applies as the fallback when no provider key is set. |
45
+ | `AUTH_MODE` | Selects the local authentication behavior used by CLI and agent flows. | Unset or `local`; this is not a browser login bypass. |
46
+ | `AGENT_NATIVE_ALLOW_BUILDER_PREVIEW_LOCAL_DEV` | Explicitly enables the existing local-dev sign-in button on approved Builder preview hosts during development. | `1` or `true`; requires development mode and must stay off public or production deployments. |
47
+ | `AUTH_DISABLED` | Disables auth for local or preview-only work. Unset already means false. | `true` or `1`; never use on a public production app. |
48
+ | `AUTH_MAGIC_LINK` | Controls the password-first versus magic-link sign-in path. | `0` keeps password-first sign-in; otherwise a configured email transport can enable magic links. |
49
+ | `AUTH_SKIP_EMAIL_VERIFICATION` | Skips signup email verification for local QA or previews. | `1`; never use it to weaken production auth. |
50
+ | `ACCESS_TOKEN` / `ACCESS_TOKENS` | Static bearer fallback for MCP and Connect clients. | One token or a delimited token list; these are not browser auth. |
51
+ | `AGENT_PROD_CODE_EXECUTION` | Production code-execution policy. | `off`, `sandboxed`, or `trusted`. See [Production Code Execution](/docs/deployment#production-code-execution). |
52
+ | `AGENT_NATIVE_SSR_CACHE` | Deployment-wide public SSR shell cache policy. | Unset/`on`, `off`, or a duration such as `30s` or `5m`. See [SSR Caching](/docs/deployment#ssr-caching). |
53
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM` | Lets a scale-to-zero database autosuspend instead of being woken every minute. | `1`; see [Keep-warm](/docs/deployment#netlify-keep-warm). |
54
+ | `AGENT_NATIVE_KEEP_WARM_SCHEDULE` | Keep-warm cadence override. | A 5-field cron expression such as `*/5 * * * *`; an unparseable value fails the build. |
55
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND` | Drops only the background-function warm and keeps the server warm. | `1`; see [Keep-warm](/docs/deployment#netlify-keep-warm). |
56
+ | `AGENT_NATIVE_DISABLE_INPROCESS_SWEEPS` | Turns off the in-process backstop sweep timers where a durable scheduler drives the same work. | `1`; queued work is not retried without another driver. |
57
+ | `AGENT_NATIVE_SKIP_ENSURE_TABLES` | Skips on-demand schema DDL for an already-migrated database. | `1`; see [On-demand schema DDL](/docs/deployment#skip-ensure-tables). You own migrations when this is set. |
58
+ | `COOKIE_DOMAIN` | Shares auth cookies across same-database subdomains when explicitly configured. | A cookie domain. |
59
+ | `CORS_ALLOWED_ORIGINS` | Cross-origin request allowlist. | A comma-separated list of exact origins. |
60
+ | `WEBHOOK_BASE_URL` | Optional public base URL for self-callback and webhook targets. | An absolute public `http(s)` origin. |
61
+ | `APP_NAME` | App identity used by workspace and app-scoped configuration. | A short app name, such as `mail`. |
62
+ | `APP_ID` / `APP_TEMPLATE` | Optional app identity and generated-template metadata. | App-owned strings. |
63
+ | `NODE_ENV` | Node runtime mode. | Normally `development`, `test`, or `production`. |
64
+ | `CI` | Marks CI-driven test and build behavior. | A CI-provided truthy value. |
65
+ | `DEBUG` | Enables resolver-specific debug logging. | A resolver-supported truthy or namespace value. |
65
66
 
66
67
  Generate strong secrets with:
67
68
 
@@ -72,7 +72,7 @@ export default defineAction({
72
72
  });
73
73
  ```
74
74
 
75
- Run it from the terminal:
75
+ Run this from the app directory:
76
76
 
77
77
  ```bash
78
78
  pnpm action analyze-text --text "Hello world. How are you today?"
@@ -82,9 +82,10 @@ Or ask the agent in chat:
82
82
 
83
83
  > Run the analyze-text action on "Hello world. How are you today?"
84
84
 
85
- The built-in `data-chart` renderer turns the structured result into a chart in
86
- the transcript. There is no renderer file or `app/root.tsx` import to add. For
87
- custom native components, see [Native Chat UI](/docs/native-chat-ui).
85
+ When the agent runs this action in chat, the built-in `data-chart` renderer
86
+ turns the structured result into a chart in the transcript. There is no renderer
87
+ file or `app/root.tsx` import to add. For custom native components, see
88
+ [Native Chat UI](/docs/native-chat-ui).
88
89
 
89
90
  ## Continue
90
91
 
@@ -6,14 +6,15 @@ description: "Build a React route that calls your action and displays its result
6
6
  # Add a Page
7
7
 
8
8
  This is part three of the Getting Started series. In [Add an Action](/docs/getting-started-actions)
9
- you created `analyze-text`. Here you'll call that same action from a route. No
10
- database is needed yet: Chat already includes the SQL runtime for when you need
11
- to persist domain data.
9
+ you created `analyze-text`. Here you'll call that same action from a route. This
10
+ example does not need a new database table. Chat already stores chat history in
11
+ SQL; add your own tables when you need to persist domain data.
12
12
 
13
13
  ## Create the route {#add-a-page}
14
14
 
15
- Route files in `app/routes/` are picked up automatically. Create
16
- `app/routes/text-analyses.tsx`; it will be available at
15
+ The dev server reads route files when it starts. Create
16
+ `app/routes/text-analyses.tsx`, then restart `pnpm dev` if it is already
17
+ running. The route will be available at
17
18
  `http://localhost:8080/text-analyses`.
18
19
 
19
20
  ```tsx filename="app/routes/text-analyses.tsx"
@@ -58,7 +59,7 @@ export default function TextAnalysesRoute() {
58
59
  ```
59
60
 
60
61
  `useActionQuery` calls the same read-only action the agent uses. The page does
61
- not need a custom API route, a second data layer, or SQL yet.
62
+ not need a custom API route, a second data layer, or a new SQL table.
62
63
 
63
64
  Open `http://localhost:8080/text-analyses`, or ask the agent:
64
65
 
@@ -6,9 +6,9 @@ description: "Create a Chat app and configure an agent, then extend it with an a
6
6
  # Getting Started
7
7
 
8
8
  Agent-Native apps give the agent and the UI the same [actions](/docs/actions),
9
- SQL data, and application state. This is the hands-on path: start with chat,
10
- then add an action and a page. SQL is already configured in Chat and becomes an
11
- optional next step when results need to persist.
9
+ SQL data, and application state. This path starts with Chat, which already
10
+ creates the framework tables it needs and stores chat history in local SQLite by
11
+ default. Add your own tables only when your app needs to persist domain data.
12
12
 
13
13
  <Steps>
14
14
 
@@ -65,4 +65,5 @@ Once the agent responds, continue with [Add an Action](/docs/getting-started-act
65
65
 
66
66
  - [What Is Agent-Native?](/docs/what-is-agent-native): the architecture behind this path.
67
67
  - [Chat Template](/docs/template-chat): what the starter app includes.
68
+ - [Database](/docs/database): add app-owned tables when your app needs domain data.
68
69
  - [FAQ](/docs/faq): answers about models, hosting, and templates.
@@ -14,7 +14,7 @@ import { notify } from "@agent-native/core/notifications";
14
14
 
15
15
  await notify(
16
16
  { severity: "info", title: "Booking confirmed", body: "Jane at 3pm" },
17
- { owner: "steve@builder.io" },
17
+ { owner: "user@example.com" },
18
18
  );
19
19
  ```
20
20
 
@@ -238,14 +238,14 @@ import {
238
238
  deleteNotification,
239
239
  } from "@agent-native/core/notifications";
240
240
 
241
- const rows = await listNotifications("steve@builder.io", {
241
+ const rows = await listNotifications("user@example.com", {
242
242
  unreadOnly: true,
243
243
  limit: 50,
244
244
  });
245
- const unread = await countUnread("steve@builder.io");
246
- await markNotificationRead(rows[0].id, "steve@builder.io");
247
- await markAllNotificationsRead("steve@builder.io");
248
- await deleteNotification(rows[0].id, "steve@builder.io");
245
+ const unread = await countUnread("user@example.com");
246
+ await markNotificationRead(rows[0].id, "user@example.com");
247
+ await markAllNotificationsRead("user@example.com");
248
+ await deleteNotification(rows[0].id, "user@example.com");
249
249
  ```
250
250
 
251
251
  Each function is owner-scoped — no cross-user reads, no cross-user writes.
@@ -15,7 +15,7 @@ import {
15
15
  } from "@agent-native/core/progress";
16
16
 
17
17
  const run = await startRun({
18
- owner: "steve@builder.io",
18
+ owner: "user@example.com",
19
19
  title: "Triage 128 unread emails",
20
20
  step: "Fetching inbox",
21
21
  });
@@ -100,7 +100,7 @@ Create a run. Returns the full `AgentRun` with a generated id.
100
100
 
101
101
  ```ts
102
102
  const run = await startRun({
103
- owner: "steve@builder.io",
103
+ owner: "user@example.com",
104
104
  title: "Ingest 1M rows",
105
105
  step: "Opening CSV",
106
106
  metadata: { jobId: "abc123", artifactPath: "s3://..." },
@@ -140,9 +140,9 @@ Also emits `run.progress.updated` with the terminal status.
140
140
  ```ts
141
141
  import { listRuns, getRun, deleteRun } from "@agent-native/core/progress";
142
142
 
143
- const active = await listRuns("steve@builder.io", { activeOnly: true });
144
- const run = await getRun("run-id", "steve@builder.io");
145
- await deleteRun("run-id", "steve@builder.io");
143
+ const active = await listRuns("user@example.com", { activeOnly: true });
144
+ const run = await getRun("run-id", "user@example.com");
145
+ await deleteRun("run-id", "user@example.com");
146
146
  ```
147
147
 
148
148
  ## HTTP API {#http}
@@ -82,7 +82,9 @@ export default function SettingsPage() {
82
82
  }
83
83
  ```
84
84
 
85
- That's it — React Router picks it up automatically, no registration needed.
85
+ That's it — React Router picks it up automatically after the route table is
86
+ rebuilt. If `pnpm dev` is already running, restart it after adding the file. No
87
+ registration is needed.
86
88
 
87
89
  ## Dynamic params {#dynamic-params}
88
90
 
@@ -5,7 +5,7 @@ description: "Connect a portable SQL database to your agent-native app: schema h
5
5
 
6
6
  # Database
7
7
 
8
- Every agent-native app stores its state in SQL. The UI and the agent both read and write the same tables through the same actions, using the same [Drizzle ORM](https://orm.drizzle.team) client. When either side changes data, the other sees it through the polling layer.
8
+ Every agent-native app stores its state in SQL. The UI and the agent both read and write the same tables through the same actions, using the same [Drizzle ORM](https://orm.drizzle.team) client. Live sync uses SSE with polling fallback, so changes appear in the other surface without a manual refresh.
9
9
 
10
10
  <Diagram id="doc-block-9mtx2f" title="How data flows to the database" summary="The UI and the agent both reach the database through the same Actions layer. Both callers use the same getDb() client and the same SQL tables. There is no separate backend for each.">
11
11
 
@@ -110,7 +110,7 @@ An app that uses the database needs three files:
110
110
 
111
111
  - `server/db/schema.ts`: table definitions
112
112
  - `server/db/index.ts`: the typed DB client singleton
113
- - `server/plugins/db.ts`: migrations that run at startup
113
+ - `server/plugins/db.ts`: app-owned migrations for local startup
114
114
 
115
115
  ### 1. Define your schema {#schema}
116
116
 
@@ -208,7 +208,8 @@ Import `getDb` from this template-local path in actions and routes. Do not impor
208
208
 
209
209
  ### 3. Write migrations {#migrations}
210
210
 
211
- Schema changes are applied at startup via a Nitro plugin in `server/plugins/db.ts`. Use `runMigrations` from `@agent-native/core/db`:
211
+ For local development, schema changes can run through a Nitro plugin in
212
+ `server/plugins/db.ts`. Use `runMigrations` from `@agent-native/core/db`:
212
213
 
213
214
  <AnnotatedCode
214
215
  id="doc-block-7qwlpz"
@@ -242,7 +243,15 @@ Schema changes are applied at startup via a Nitro plugin in `server/plugins/db.t
242
243
  ]}
243
244
  />
244
245
 
245
- `runMigrations` runs each entry in order once, then records the version so it is skipped on future restarts. Entries are idempotent. The plugin is safe to call on every boot.
246
+ `runMigrations` runs each pending entry in order once, records it as applied, and
247
+ skips it on later runs. Give new entries a stable `name`; named migrations are
248
+ tracked independently of their version number.
249
+
250
+ <Callout tone="warning">
251
+ For production or serverless deployments, run migrations in a release or
252
+ deploy step instead of on the first request. The Chat template provides `pnpm
253
+ migrate:production` for this.
254
+ </Callout>
246
255
 
247
256
  <Callout tone="warning">
248
257
  Give every new migration a stable `name` (e.g. `{ version: 4, name:
@@ -85,7 +85,7 @@ The `server/` directory is the infrastructure layer of an agent-native app. It h
85
85
 
86
86
  ## Where the Server Fits {#role}
87
87
 
88
- In a traditional web app, the server is where most logic lives. Business rules, data access, and presentation all happen inside route handlers. Agent-native apps work differently. Logic lives in actions, which the agent and UI share as equal partners. The server's job is coordination: run database migrations, configure authentication, mount the agent loop, and handle the narrow set of HTTP concerns that actions can't express on their own.
88
+ In a traditional web app, the server is where most logic lives. Business rules, data access, and presentation all happen inside route handlers. Agent-native apps work differently. Logic lives in actions, which the agent and UI share as equal partners. The server's job is coordination: apply app-owned database migrations, configure authentication, mount the agent loop, and handle the narrow set of HTTP concerns that actions can't express on their own.
89
89
 
90
90
  <Diagram id="doc-block-server-overview-2" title="Traditional server vs. Agent Native">
91
91
 
@@ -194,19 +194,19 @@ Browser requests, the agent loop, and external API clients all route through the
194
194
 
195
195
  These are the directories and files inside `server/` that every agent-native app ships. Each corresponds to a specific piece of the server layer: what it does, when to reach for it, and how it connects to the rest of the framework.
196
196
 
197
- | Page | What it covers |
198
- | ----------------------------------------- | ----------------------------------------------------------------------------------- |
199
- | **[Database](/docs/server-database)** | Schema definition with `table()` helpers, `getDb`, and ownable table patterns |
200
- | **[Middleware](/docs/server-middleware)** | Auth guards in `server/middleware/` and why they run there instead of in a plugin |
201
- | **[Plugins](/docs/server-plugins)** | The three startup plugins every app ships: db migrations, auth, and agent-chat |
202
- | **[Routes](/docs/server-routes)** | File-based routes, the SSR catch-all, and scoping custom routes to the request user |
197
+ | Page | What it covers |
198
+ | ----------------------------------------- | ------------------------------------------------------------------------------------ |
199
+ | **[Database](/docs/server-database)** | Schema definition with `table()` helpers, `getDb`, and ownable table patterns |
200
+ | **[Middleware](/docs/server-middleware)** | Auth guards in `server/middleware/` and why they run there instead of in a plugin |
201
+ | **[Plugins](/docs/server-plugins)** | Startup plugins for auth and agent-chat, plus optional app-owned database migrations |
202
+ | **[Routes](/docs/server-routes)** | File-based routes, the SSR catch-all, and scoping custom routes to the request user |
203
203
 
204
204
  ## Nitro {#nitro}
205
205
 
206
206
  [Nitro](https://nitro.build) is the server toolkit that powers the agent-native HTTP layer. Most of what you'll configure in `server/` is Nitro: file-based routes, startup plugins, and middleware.
207
207
 
208
208
  - **File-based routing**: the filename maps directly to an HTTP method and URL path, with no registration needed. `server/routes/api/health.get.ts` becomes `GET /api/health` automatically. Visit [Routes](/docs/server-routes) for more details.
209
- - **Plugins**: code that runs once at server startup, before any request is served. Database migrations, auth configuration, and the agent-chat mount all happen in `server/plugins/`. Visit [Plugins](/docs/server-plugins) for more details.
209
+ - **Plugins**: code registered at server startup and loaded once. Framework helpers initialize auth and the agent-chat mount; optional app-owned database migrations may still be running when the first request arrives. Visit [Plugins](/docs/server-plugins) for more details.
210
210
  - **Middleware**: code that runs on every incoming request before it reaches a route. The auth guard lives in `server/middleware/`. Visit [Middleware](/docs/server-middleware) for more details.
211
211
 
212
212
  Nitro is also deployment-agnostic. The same app deploys to Node.js, Cloudflare Workers, Netlify, Vercel, and other runtimes with no code changes. Just set a preset. See [Deployment](/docs/deployment).
@@ -230,5 +230,5 @@ Use custom `/api/*` routes only when you need a route-shaped protocol or binary/
230
230
  - [**Actions**](/docs/actions): the default operation surface. Reach for a custom route only when it doesn't fit.
231
231
  - [**Database**](/docs/server-database): the `getDb()`/schema pattern custom routes and actions both import
232
232
  - [**Middleware**](/docs/server-middleware): auth guards and the `server/middleware/` directory
233
- - [**Plugins**](/docs/server-plugins): startup plugins for migrations, auth, and the agent
233
+ - [**Plugins**](/docs/server-plugins): startup plugins for auth, the agent, and optional app-owned migrations
234
234
  - [**Routes**](/docs/server-routes): file-based routes, request context, and the SSR catch-all
@@ -5,7 +5,7 @@ description: "Startup plugins in server/plugins/ — what they are, the two plug
5
5
 
6
6
  # Plugins
7
7
 
8
- Plugins are startup hooks. Each file in `server/plugins/` exports a function that Nitro calls once when the server initializes, before any route is served. They are the right place for one-time setup: configuring auth, mounting the agent loop, running database migrations, or registering any other initialization code that needs to complete before requests arrive.
8
+ Plugins are startup hooks. Nitro loads each file in `server/plugins/` once when the server initializes. They are the right place for one-time setup: configuring auth, mounting the agent loop, running database migrations, or registering other initialization code. Framework helpers coordinate their async setup; custom plugin work may still be in flight when the first request arrives.
9
9
 
10
10
  Nitro discovers plugins automatically from the filesystem. No registration or imports are required. Files run in alphabetical order, so execution order is controlled by filename prefix.
11
11
 
@@ -21,7 +21,7 @@ Apps that need custom database tables add a third:
21
21
 
22
22
  ```text
23
23
  server/plugins/
24
- db.ts -> run migrations on startup
24
+ db.ts -> register app-owned migrations for local startup
25
25
  ```
26
26
 
27
27
  ## Auth Plugin {#auth-plugin}
@@ -80,7 +80,7 @@ screen when context matters.`,
80
80
 
81
81
  ## Database Plugin {#database-plugin}
82
82
 
83
- If your app defines custom database tables, add `server/plugins/db.ts` to run schema migrations at startup. It uses `runMigrations` from `@agent-native/core/db`:
83
+ If your app defines custom database tables, add `server/plugins/db.ts` to register schema migrations for local startup. It uses `runMigrations` from `@agent-native/core/db`:
84
84
 
85
85
  ```ts filename="server/plugins/db.ts"
86
86
  import { runMigrations } from "@agent-native/core/db";
@@ -110,6 +110,12 @@ Each entry needs a `version` number and a `sql` string. Give it a stable `name`
110
110
  TABLE ... DROP COLUMN`, `DELETE FROM`) in startup plugins.
111
111
  </Callout>
112
112
 
113
+ <Callout tone="warning">
114
+ For production or serverless deployments, run migrations in a release or
115
+ deploy step instead of on the first request. The Chat template provides `pnpm
116
+ migrate:production` for this.
117
+ </Callout>
118
+
113
119
  ## Writing Custom Plugins {#custom-plugins}
114
120
 
115
121
  The framework helpers (`createAuthPlugin`, `createAgentChatPlugin`, `runMigrations`) each return a Nitro plugin function. For anything outside those helpers, write a plugin using `defineNitroPlugin`:
@@ -142,6 +148,6 @@ If you add custom plugins, prefix their filenames to control invocation order, b
142
148
 
143
149
  - [**Database**](/docs/server-database): schema helpers and the `getDb` pattern used inside plugins
144
150
  - [**Middleware**](/docs/server-middleware): the auth guard that enforces what the auth plugin configures
145
- - [**Routes**](/docs/server-routes): custom file routes served after plugins complete
151
+ - [**Routes**](/docs/server-routes): custom file routes and when to use them
146
152
  - [**Writing Agent Instructions**](/docs/writing-agent-instructions): how to craft the `systemPrompt` in the agent-chat plugin
147
153
  - [**Nitro plugin docs**](https://nitro.build/guide/plugins): the full plugin API and lifecycle hooks