@agent-native/core 0.164.4 → 0.164.12
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.
- package/corpus/README.md +1 -1
- package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +84 -0
- package/corpus/templates/calendar/AGENTS.md +5 -0
- package/corpus/templates/calendar/actions/delete-event.ts +1 -1
- package/corpus/templates/calendar/actions/delete-events.ts +508 -0
- package/corpus/templates/calendar/actions/event-action-helpers.ts +1 -1
- package/corpus/templates/calendar/actions/list-events.ts +53 -0
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +36 -47
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +3 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +18 -1
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +256 -38
- package/corpus/templates/calendar/app/hooks/use-google-auth.ts +43 -3
- package/corpus/templates/calendar/app/i18n-data.ts +120 -0
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +113 -0
- package/corpus/templates/calendar/changelog/2026-08-18-the-agent-can-now-remove-many-meetings-at-once-such-as-every.md +6 -0
- package/corpus/templates/calendar/server/handlers/google-auth.ts +119 -3
- package/corpus/templates/calendar/server/lib/event-weekday.ts +112 -0
- package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/calendar/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/calendar/server/routes/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/clips/app/components/player/video-player.tsx +12 -0
- package/corpus/templates/clips/app/routes/_app.dictate.tsx +18 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +114 -20
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +83 -78
- package/corpus/templates/clips/changelog/2026-08-19-clips-nightly-builds-are-available-for-trying-the-latest-upd.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-19-social-preview-video-frames.md +1 -0
- package/corpus/templates/clips/desktop/README.md +19 -4
- package/corpus/templates/clips/desktop/src/app.tsx +78 -16
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -2
- package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -0
- package/corpus/templates/clips/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.get.ts +41 -3
- package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/clips/server/routes/_agent-native/google/callback.get.ts +22 -1
- package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +41 -22
- package/corpus/templates/factory/AGENTS.md +3 -2
- package/corpus/templates/factory/actions/get-factory-graph-version.ts +69 -0
- package/corpus/templates/factory/actions/list-factory-automations.ts +4 -0
- package/corpus/templates/factory/actions/list-factory-graph-versions.ts +82 -0
- package/corpus/templates/factory/actions/restore-factory-graph-version.ts +163 -0
- package/corpus/templates/factory/actions/save-factory-graph.ts +93 -60
- package/corpus/templates/factory/actions/start-builder-for-item.ts +19 -17
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +100 -36
- package/corpus/templates/factory/app/components/factory/FactoryHistoryView.tsx +709 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +62 -2
- package/corpus/templates/factory/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +47 -0
- package/corpus/templates/factory/app/routes/factory.tsx +324 -61
- package/corpus/templates/factory/server/connectors/slack.ts +44 -2
- package/corpus/templates/factory/server/plugins/agent-chat.ts +12 -8
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +13 -0
- package/corpus/templates/factory/server/triage/slack-client.ts +5 -0
- package/corpus/templates/factory/server/triage/slack-poller.ts +72 -4
- package/corpus/templates/mail/actions/view-screen.ts +1 -1
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -18
- package/corpus/templates/mail/server/handlers/google-auth.ts +125 -24
- package/corpus/templates/mail/server/lib/gmail-query.ts +5 -2
- package/corpus/templates/mail/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/mail/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/mail/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/mail/server/routes/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +0 -12
- package/corpus/templates/plan/changelog/2026-08-19-plan-prompts-now-guide-you-to-connect-ai-before-sending-and-.md +6 -0
- package/corpus/templates/slides/actions/approve-deck-access-request.ts +234 -0
- package/corpus/templates/slides/actions/get-deck-access-status.ts +35 -2
- package/corpus/templates/slides/actions/request-deck-access.ts +263 -64
- package/corpus/templates/slides/app/components/editor/MissingDeckAccessPane.tsx +196 -0
- package/corpus/templates/slides/app/components/editor/RequestDeckAccessDialog.tsx +101 -0
- package/corpus/templates/slides/app/hooks/use-deck-access.ts +7 -4
- package/corpus/templates/slides/app/i18n/en-US.ts +29 -6
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +147 -169
- package/corpus/templates/slides/app/routes/access-request.approve.tsx +250 -0
- package/corpus/templates/slides/server/db/schema.ts +8 -0
- package/corpus/templates/slides/server/lib/access-request-email.ts +36 -0
- package/corpus/templates/slides/server/lib/emails.ts +26 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +7 -0
- package/corpus/templates/slides/server/plugins/db.ts +50 -0
- package/corpus/templates/slides/shared/deck-access.ts +31 -0
- package/dist/a2a/task-store.d.ts +1 -0
- package/dist/a2a/task-store.js +1 -1
- package/dist/agent/observational-memory/store.d.ts +1 -0
- package/dist/agent/observational-memory/store.js +1 -1
- package/dist/agent/run-store.d.ts +1 -0
- package/dist/agent/run-store.js +1 -1
- package/dist/agent/tool-approval-store.d.ts +1 -0
- package/dist/agent/tool-approval-store.js +1 -1
- package/dist/application-state/store.d.ts +1 -0
- package/dist/application-state/store.js +1 -1
- package/dist/browser-sessions/store.d.ts +1 -0
- package/dist/browser-sessions/store.js +1 -1
- package/dist/checkpoints/store.d.ts +1 -0
- package/dist/checkpoints/store.js +1 -1
- package/dist/cli/code-agent-schedules.d.ts +11 -0
- package/dist/cli/code-agent-schedules.js +44 -5
- package/dist/client/AgentPanel.d.ts +5 -1
- package/dist/client/AgentPanel.js +2 -2
- package/dist/client/AssistantChat.d.ts +5 -1
- package/dist/client/AssistantChat.js +40 -6
- package/dist/client/EnvironmentBadge.d.ts +7 -13
- package/dist/client/EnvironmentBadge.js +43 -92
- package/dist/client/agent-chat/index.d.ts +1 -0
- package/dist/client/agent-chat/index.js +1 -0
- package/dist/client/agent-chat-adapter.js +76 -50
- package/dist/client/app-providers.js +4 -4
- package/dist/client/chat/message-components.d.ts +4 -0
- package/dist/client/chat/message-components.js +28 -1
- package/dist/client/chat/run-recovery.js +26 -0
- package/dist/client/chat-first/apps-rail.d.ts +1 -0
- package/dist/client/chat-first/apps-rail.js +28 -2
- package/dist/client/sse-event-processor.js +13 -8
- package/dist/client/use-active-agent-chat-run.d.ts +2 -0
- package/dist/client/use-active-agent-chat-run.js +22 -0
- package/dist/coding-tools/sandbox/executions-store.d.ts +1 -0
- package/dist/coding-tools/sandbox/executions-store.js +1 -1
- package/dist/collab/awareness-store.d.ts +1 -0
- package/dist/collab/awareness-store.js +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/storage.d.ts +1 -0
- package/dist/collab/storage.js +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.js +3 -3
- package/dist/db/ddl-guard.js +8 -0
- package/dist/db/migration-runtime.d.ts +23 -0
- package/dist/db/migration-runtime.js +41 -0
- package/dist/db/migrations.d.ts +1 -2
- package/dist/db/migrations.js +2 -24
- package/dist/email-catalog/log.d.ts +1 -0
- package/dist/email-catalog/log.js +1 -1
- package/dist/guards/index.d.ts +1 -0
- package/dist/guards/index.js +1 -0
- package/dist/guards/release-schema-complete.d.ts +22 -0
- package/dist/guards/release-schema-complete.js +144 -0
- package/dist/integrations/a2a-continuations-store.d.ts +1 -0
- package/dist/integrations/a2a-continuations-store.js +1 -1
- package/dist/integrations/awaiting-input-store.d.ts +1 -0
- package/dist/integrations/awaiting-input-store.js +1 -1
- package/dist/integrations/config-store.d.ts +1 -0
- package/dist/integrations/config-store.js +1 -1
- package/dist/integrations/controls-store.d.ts +1 -0
- package/dist/integrations/controls-store.js +1 -1
- package/dist/integrations/identity-links-store.d.ts +1 -0
- package/dist/integrations/identity-links-store.js +1 -1
- package/dist/integrations/installations-store.d.ts +1 -0
- package/dist/integrations/installations-store.js +1 -1
- package/dist/integrations/remote-commands-store.d.ts +1 -0
- package/dist/integrations/remote-commands-store.js +1 -1
- package/dist/integrations/remote-devices-store.d.ts +1 -0
- package/dist/integrations/remote-devices-store.js +1 -1
- package/dist/integrations/remote-push-store.d.ts +1 -0
- package/dist/integrations/remote-push-store.js +1 -1
- package/dist/integrations/remote-run-events-store.d.ts +1 -0
- package/dist/integrations/remote-run-events-store.js +1 -1
- package/dist/integrations/scope-store.d.ts +1 -0
- package/dist/integrations/scope-store.js +1 -1
- package/dist/integrations/thread-mapping-store.d.ts +1 -0
- package/dist/integrations/thread-mapping-store.js +1 -1
- package/dist/integrations/usage-budget-store.d.ts +1 -0
- package/dist/integrations/usage-budget-store.js +1 -1
- package/dist/jobs/background-automation-runner.js +111 -9
- package/dist/jobs/run-history.d.ts +1 -0
- package/dist/jobs/run-history.js +1 -1
- package/dist/jobs/scheduler-health.d.ts +1 -0
- package/dist/jobs/scheduler-health.js +1 -1
- package/dist/mcp/approval-store.d.ts +1 -0
- package/dist/mcp/approval-store.js +1 -1
- package/dist/mcp/connect-store.d.ts +1 -0
- package/dist/mcp/connect-store.js +1 -1
- package/dist/mcp/oauth-store.d.ts +1 -0
- package/dist/mcp/oauth-store.js +1 -1
- package/dist/notifications/store.d.ts +1 -0
- package/dist/notifications/store.js +1 -1
- package/dist/oauth-tokens/store.d.ts +1 -0
- package/dist/oauth-tokens/store.js +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/progress/store.d.ts +1 -0
- package/dist/progress/store.js +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
- package/dist/provider-api/actions/provider-api.d.ts +4 -4
- package/dist/provider-api/corpus-jobs-store.d.ts +1 -0
- package/dist/provider-api/corpus-jobs-store.js +1 -1
- package/dist/provider-api/custom-registry.d.ts +1 -0
- package/dist/provider-api/custom-registry.js +1 -1
- package/dist/provider-api/quota-governor.d.ts +1 -0
- package/dist/provider-api/quota-governor.js +1 -1
- package/dist/provider-api/staged-datasets-store.d.ts +1 -0
- package/dist/provider-api/staged-datasets-store.js +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/resources/store.d.ts +1 -0
- package/dist/resources/store.js +1 -1
- package/dist/scripts/dev/index.js +15 -1
- package/dist/search/index.js +3 -0
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/secrets/storage.d.ts +1 -0
- package/dist/secrets/storage.js +1 -1
- package/dist/server/agent-chat-plugin.js +38 -9
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-teams-run-queue.d.ts +1 -0
- package/dist/server/agent-teams-run-queue.js +1 -1
- package/dist/server/auth-marketing.js +3 -1
- package/dist/server/auth.d.ts +18 -1
- package/dist/server/auth.js +370 -154
- package/dist/server/embed-session.d.ts +1 -0
- package/dist/server/embed-session.js +1 -1
- package/dist/server/google-auth-plugin.js +3 -1
- package/dist/server/google-oauth.d.ts +10 -0
- package/dist/server/google-oauth.js +25 -1
- package/dist/server/identity-sso-store.d.ts +1 -0
- package/dist/server/identity-sso-store.js +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/onboarding-html.js +200 -31
- package/dist/server/poll.d.ts +2 -0
- package/dist/server/poll.js +19 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/release-migrations.js +5 -0
- package/dist/server/release-schema.d.ts +46 -0
- package/dist/server/release-schema.js +307 -0
- package/dist/settings/store.d.ts +1 -0
- package/dist/settings/store.js +1 -1
- package/dist/shared/environment-lanes.d.ts +28 -0
- package/dist/shared/environment-lanes.js +61 -0
- package/dist/sharing/actions/share-resource.js +22 -2
- package/dist/styles/agent-native.css +17 -15
- package/dist/triggers/routes.d.ts +11 -0
- package/dist/triggers/routes.js +10 -0
- package/dist/usage/alerts-store.d.ts +1 -0
- package/dist/usage/alerts-store.js +1 -1
- package/dist/usage/store.d.ts +1 -0
- package/dist/usage/store.js +1 -1
- package/docs/content/actions-access-control.mdx +136 -2
- package/docs/content/actions-agent-tools.mdx +101 -0
- package/docs/content/actions-defining.mdx +2 -2
- package/docs/content/audit-log.mdx +1 -1
- package/docs/content/authentication.mdx +1 -1
- package/docs/content/cloudflare.mdx +43 -0
- package/docs/content/creating-templates.mdx +1 -1
- package/docs/content/deploy-an-app.mdx +109 -0
- package/docs/content/deployment-environment-variables.mdx +101 -0
- package/docs/content/deployment.mdx +125 -792
- package/docs/content/docs-components.mdx +2 -2
- package/docs/content/environment-variables.mdx +41 -41
- package/docs/content/file-uploads.mdx +74 -40
- package/docs/content/harness-agents.mdx +2 -2
- package/docs/content/internationalization.mdx +61 -65
- package/docs/content/key-concepts.mdx +3 -3
- package/docs/content/multi-app-workspace.mdx +2 -2
- package/docs/content/netlify.mdx +47 -0
- package/docs/content/node-docker.mdx +138 -0
- package/docs/content/organizations-teams-permissions.mdx +5 -5
- package/docs/content/other-platforms.mdx +27 -0
- package/docs/content/ssr-caching.mdx +45 -0
- package/docs/content/template-assets-developers.mdx +2 -2
- package/docs/content/template-chat-developers.mdx +2 -2
- package/docs/content/template-content-developers.mdx +2 -2
- package/docs/content/{local-file-mode.mdx → template-content-local-files.mdx} +2 -1
- package/docs/content/template-content-sync.mdx +2 -2
- package/docs/content/toolkit-agent-ux.mdx +1 -1
- package/docs/content/toolkit-resources.mdx +2 -2
- package/docs/content/updating-ui-in-production.mdx +35 -0
- package/docs/content/vercel.mdx +38 -0
- package/docs/content/what-is-agent-native.mdx +1 -1
- package/docs/content/workspace-deployment.mdx +350 -0
- package/package.json +2 -2
- package/docs/content/agents.mdx +0 -9
- package/docs/content/database.mdx +0 -317
- package/docs/content/human-approval.mdx +0 -156
|
@@ -1,845 +1,178 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Deployment"
|
|
3
|
-
description: "Deploy
|
|
3
|
+
description: "Deploy an Agent-Native app or workspace to a Nitro-compatible platform with a persistent SQL database."
|
|
4
|
+
search: "deployment deploy app workspace hosting database Nitro Vercel Netlify Cloudflare Node.js"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Deployment
|
|
7
8
|
|
|
8
|
-
Agent-
|
|
9
|
+
Agent-Native apps run on [Nitro](https://nitro.build), so the same app can
|
|
10
|
+
deploy to Node.js, serverless functions, edge workers, or a managed host. Pick
|
|
11
|
+
the path that matches what you are shipping:
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
<Cards columns={2}>
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
### :server: [Deploy an app](/docs/deploy-an-app)
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
Build and launch one standalone app, or deploy one app from a workspace on its
|
|
18
|
+
own domain.
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
### :network: [Deploy a workspace](/docs/workspace-deployment)
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
Build several apps behind one origin with shared login and same-origin app to
|
|
23
|
+
app communication.
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
npx @agent-native/core@latest create my-app --standalone --template chat
|
|
23
|
-
cd my-app
|
|
24
|
-
pnpm install
|
|
25
|
-
```
|
|
25
|
+
</Cards>
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
### 2. Add the local Docker files
|
|
30
|
-
|
|
31
|
-
Create `Dockerfile`, `.dockerignore`, and `docker-compose.yml` in the app root. `docker compose up --build` needs the Dockerfile, and `.dockerignore` keeps host-only files such as `node_modules` out of the Linux build context. Compose starts Postgres only on the private Compose network.
|
|
32
|
-
|
|
33
|
-
You can also download the [Dockerfile](https://www.agent-native.com/examples/self-hosted-chat/Dockerfile), [.dockerignore](https://www.agent-native.com/examples/self-hosted-chat/.dockerignore), [Compose file](https://www.agent-native.com/examples/self-hosted-chat/docker-compose.yml), and [environment template](https://www.agent-native.com/examples/self-hosted-chat/env.example) as a starter fixture. The [Dockerfile](#docker) below matches the fixture.
|
|
34
|
-
|
|
35
|
-
```yaml filename="docker-compose.yml" maxLines=40
|
|
36
|
-
services:
|
|
37
|
-
app:
|
|
38
|
-
build: .
|
|
39
|
-
ports:
|
|
40
|
-
- "127.0.0.1:3000:3000"
|
|
41
|
-
environment:
|
|
42
|
-
DATABASE_URL: postgres://agent_native@postgres:5432/agent_native
|
|
43
|
-
BETTER_AUTH_SECRET: local-development-secret-change-me-1234567890
|
|
44
|
-
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
|
|
45
|
-
depends_on:
|
|
46
|
-
postgres:
|
|
47
|
-
condition: service_healthy
|
|
48
|
-
|
|
49
|
-
postgres:
|
|
50
|
-
image: postgres:18
|
|
51
|
-
environment:
|
|
52
|
-
POSTGRES_DB: agent_native
|
|
53
|
-
POSTGRES_USER: agent_native
|
|
54
|
-
POSTGRES_HOST_AUTH_METHOD: trust
|
|
55
|
-
volumes:
|
|
56
|
-
- postgres-data-v18:/var/lib/postgresql
|
|
57
|
-
healthcheck:
|
|
58
|
-
test: ["CMD-SHELL", "pg_isready -U agent_native -d agent_native"]
|
|
59
|
-
interval: 5s
|
|
60
|
-
timeout: 5s
|
|
61
|
-
retries: 10
|
|
62
|
-
|
|
63
|
-
volumes:
|
|
64
|
-
postgres-data-v18:
|
|
65
|
-
```
|
|
27
|
+
## Before you deploy: choose a persistent database {#persistent-database}
|
|
66
28
|
|
|
67
|
-
|
|
29
|
+
Every deployed app needs a persistent SQL database. Local development can use
|
|
30
|
+
the SQLite file at `data/app.db`, but container, preview, and serverless
|
|
31
|
+
filesystems can be reset at any time.
|
|
68
32
|
|
|
69
|
-
|
|
33
|
+
<Steps>
|
|
70
34
|
|
|
71
|
-
|
|
72
|
-
docker compose up --build
|
|
73
|
-
```
|
|
35
|
+
### Choose a provider
|
|
74
36
|
|
|
75
|
-
|
|
37
|
+
Use any Drizzle-compatible SQL backend, such as Postgres, Neon, Supabase,
|
|
38
|
+
Railway, RDS, Turso, or libSQL. The framework detects the database dialect from
|
|
39
|
+
the connection URL.
|
|
76
40
|
|
|
77
|
-
|
|
41
|
+
### Set the connection string
|
|
78
42
|
|
|
79
|
-
|
|
43
|
+
Set `DATABASE_URL` in the deployment environment before the first production
|
|
44
|
+
deploy. Use `DATABASE_AUTH_TOKEN` too when the provider requires a separate
|
|
45
|
+
token, such as Turso or libSQL.
|
|
80
46
|
|
|
81
|
-
|
|
47
|
+
### Add production secrets
|
|
82
48
|
|
|
83
|
-
Set `
|
|
49
|
+
Set a stable `BETTER_AUTH_SECRET` for a standalone app. A workspace also needs
|
|
50
|
+
`A2A_SECRET` when it uses signed cross-app requests or background handoffs. The
|
|
51
|
+
[deployment environment reference](/docs/deployment-environment-variables)
|
|
52
|
+
covers the rest of the production configuration.
|
|
84
53
|
|
|
85
|
-
|
|
54
|
+
</Steps>
|
|
86
55
|
|
|
87
|
-
|
|
56
|
+
<Callout tone="info">
|
|
88
57
|
|
|
89
|
-
|
|
58
|
+
In a workspace, every app inherits the root `DATABASE_URL` by default. Set
|
|
59
|
+
`<APP_NAME>_DATABASE_URL` only when one app needs a different database.
|
|
90
60
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
# https://your-agents.com/calendar/* → apps/calendar
|
|
95
|
-
# https://your-agents.com/forms/* → apps/forms
|
|
96
|
-
```
|
|
61
|
+
</Callout>
|
|
62
|
+
|
|
63
|
+
## Supported deployment targets
|
|
97
64
|
|
|
98
|
-
|
|
65
|
+
Set a Nitro preset for the target you choose. The app code and database
|
|
66
|
+
contract stay the same.
|
|
99
67
|
|
|
100
|
-
<Diagram id="doc-block-
|
|
68
|
+
<Diagram id="doc-block-deployment-targets" title="Supported deployment targets" summary="Agent-Native apps can deploy to Node.js, Vercel, Netlify, Cloudflare, AWS Lambda, and Deno Deploy. Provider logos are shown for the hosted targets with first-party deployment pages.">
|
|
101
69
|
|
|
102
70
|
```html
|
|
103
|
-
<div class="
|
|
104
|
-
<
|
|
105
|
-
<
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
</
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
71
|
+
<div class="deployment-target-grid">
|
|
72
|
+
<a class="deployment-target" href="/docs/node-docker">
|
|
73
|
+
<span class="deployment-target-mark text-mark">N</span>
|
|
74
|
+
<strong>Node.js</strong>
|
|
75
|
+
</a>
|
|
76
|
+
<a class="deployment-target" href="/docs/vercel">
|
|
77
|
+
<span class="deployment-target-mark">
|
|
78
|
+
<img src="/integration-logos/vercel.svg" alt="" />
|
|
79
|
+
</span>
|
|
80
|
+
<strong>Vercel</strong>
|
|
81
|
+
</a>
|
|
82
|
+
<a class="deployment-target" href="/docs/netlify">
|
|
83
|
+
<span class="deployment-target-mark">
|
|
84
|
+
<img src="/integration-logos/netlify.svg" alt="" />
|
|
85
|
+
</span>
|
|
86
|
+
<strong>Netlify</strong>
|
|
87
|
+
</a>
|
|
88
|
+
<a class="deployment-target" href="/docs/cloudflare">
|
|
89
|
+
<span class="deployment-target-mark">
|
|
90
|
+
<img src="/integration-logos/cloudflare.svg" alt="" />
|
|
91
|
+
</span>
|
|
92
|
+
<strong>Cloudflare</strong>
|
|
93
|
+
</a>
|
|
94
|
+
<a class="deployment-target" href="/docs/other-platforms#aws-lambda">
|
|
95
|
+
<span class="deployment-target-mark text-mark">AWS</span>
|
|
96
|
+
<strong>AWS Lambda</strong>
|
|
97
|
+
</a>
|
|
98
|
+
<a class="deployment-target" href="/docs/other-platforms#deno-deploy">
|
|
99
|
+
<span class="deployment-target-mark text-mark">D</span>
|
|
100
|
+
<strong>Deno Deploy</strong>
|
|
101
|
+
</a>
|
|
123
102
|
</div>
|
|
124
103
|
```
|
|
125
104
|
|
|
126
105
|
```css
|
|
127
|
-
.
|
|
128
|
-
display:
|
|
129
|
-
|
|
130
|
-
gap:
|
|
131
|
-
flex-wrap: wrap;
|
|
132
|
-
}
|
|
133
|
-
.diagram-ws .diagram-panel {
|
|
134
|
-
display: flex;
|
|
135
|
-
flex-direction: column;
|
|
136
|
-
gap: 6px;
|
|
137
|
-
padding: 14px 16px;
|
|
106
|
+
.deployment-target-grid {
|
|
107
|
+
display: grid;
|
|
108
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
109
|
+
gap: 10px;
|
|
138
110
|
}
|
|
139
|
-
.
|
|
111
|
+
.deployment-target {
|
|
140
112
|
display: flex;
|
|
141
113
|
align-items: center;
|
|
142
|
-
gap:
|
|
114
|
+
gap: 10px;
|
|
115
|
+
min-height: 58px;
|
|
116
|
+
padding: 10px 12px;
|
|
117
|
+
border: 1px solid hsl(var(--border));
|
|
118
|
+
border-radius: 10px;
|
|
119
|
+
color: inherit;
|
|
120
|
+
text-decoration: none;
|
|
143
121
|
}
|
|
144
|
-
.
|
|
145
|
-
|
|
146
|
-
flex-direction: column;
|
|
147
|
-
gap: 8px;
|
|
148
|
-
align-items: flex-start;
|
|
122
|
+
.deployment-target:hover {
|
|
123
|
+
border-color: hsl(var(--primary));
|
|
149
124
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
- **Shared login session** — log into any app, every app is logged in.
|
|
157
|
-
- **Zero-config cross-app A2A** — tagging `@calendar` from mail is a same-origin fetch; no CORS, no JWT signing between siblings.
|
|
158
|
-
|
|
159
|
-
Publish the output with:
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
wrangler pages deploy dist
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
For Netlify unified deploys, use the Netlify preset:
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
npx @agent-native/core@latest deploy --preset netlify
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
For Vercel unified deploys, use the Vercel preset:
|
|
172
|
-
|
|
173
|
-
```bash
|
|
174
|
-
npx @agent-native/core@latest deploy --preset vercel
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
When configuring a provider build command, use the same command with `--build-only`. Vercel should run `npx @agent-native/core@latest deploy --preset vercel --build-only`; the command writes `.vercel/output` directly, so no `vercel.json` is required for workspace routing.
|
|
178
|
-
|
|
179
|
-
Hosted workspace builds require `A2A_SECRET` in the deploy provider environment.
|
|
180
|
-
This makes Slack, inbound webhooks, and cross-app A2A resume work through signed
|
|
181
|
-
background processors. Local `--build-only` artifact checks still run without it.
|
|
182
|
-
|
|
183
|
-
Per-app independent deploy is still supported — just `cd apps/<name> && npx @agent-native/core@latest build` like a standalone scaffold.
|
|
184
|
-
|
|
185
|
-
## How It Works {#how-it-works}
|
|
186
|
-
|
|
187
|
-
When you run `npx @agent-native/core@latest build`, Nitro builds both the client SPA and the server API into `.output/`:
|
|
188
|
-
|
|
189
|
-
<FileTree
|
|
190
|
-
id="doc-block-1vbo81"
|
|
191
|
-
title="Build output"
|
|
192
|
-
entries={[
|
|
193
|
-
{
|
|
194
|
-
path: ".output/",
|
|
195
|
-
note: "self-contained — copy to any environment and run",
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
path: ".output/public/",
|
|
199
|
-
note: "built SPA (static assets)",
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
path: ".output/server/index.mjs",
|
|
203
|
-
note: "server entry point",
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
path: ".output/server/chunks/",
|
|
207
|
-
note: "server code chunks",
|
|
208
|
-
},
|
|
209
|
-
]}
|
|
210
|
-
/>
|
|
211
|
-
|
|
212
|
-
The output is self-contained — copy `.output/` to any environment and run it.
|
|
213
|
-
|
|
214
|
-
<Diagram id="doc-block-1gqwzzp" title="Build to deploy" summary={"One source tree builds to a Nitro preset; the same self-contained output runs on Node, Vercel, Netlify, Cloudflare, AWS, or Deno. Every instance points at the same persistent DATABASE_URL."}>
|
|
215
|
-
|
|
216
|
-
```html
|
|
217
|
-
<div class="diagram-deploy">
|
|
218
|
-
<div class="diagram-box" data-rough>App source</div>
|
|
219
|
-
<div class="diagram-arrow diagram-muted" aria-hidden="true">→</div>
|
|
220
|
-
<div class="diagram-panel center" data-rough>
|
|
221
|
-
<span class="diagram-pill accent">build</span
|
|
222
|
-
><small class="diagram-muted">Nitro preset</small>
|
|
223
|
-
</div>
|
|
224
|
-
<div class="diagram-arrow diagram-muted" aria-hidden="true">→</div>
|
|
225
|
-
<div class="diagram-grid">
|
|
226
|
-
<span class="diagram-pill">Node.js</span
|
|
227
|
-
><span class="diagram-pill">Vercel</span
|
|
228
|
-
><span class="diagram-pill">Netlify</span
|
|
229
|
-
><span class="diagram-pill">Cloudflare</span
|
|
230
|
-
><span class="diagram-pill">AWS Lambda</span
|
|
231
|
-
><span class="diagram-pill">Deno</span>
|
|
232
|
-
</div>
|
|
233
|
-
<div class="diagram-arrow diagram-muted" aria-hidden="true">→</div>
|
|
234
|
-
<div class="diagram-box" data-rough>
|
|
235
|
-
Persistent DATABASE_URL<br /><small class="diagram-muted"
|
|
236
|
-
>shared by every instance</small
|
|
237
|
-
>
|
|
238
|
-
</div>
|
|
239
|
-
</div>
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
```css
|
|
243
|
-
.diagram-deploy {
|
|
244
|
-
display: flex;
|
|
245
|
-
align-items: center;
|
|
246
|
-
gap: 12px;
|
|
247
|
-
flex-wrap: wrap;
|
|
125
|
+
.deployment-target-mark {
|
|
126
|
+
display: grid;
|
|
127
|
+
width: 30px;
|
|
128
|
+
height: 30px;
|
|
129
|
+
place-items: center;
|
|
130
|
+
flex: 0 0 auto;
|
|
248
131
|
}
|
|
249
|
-
.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
gap: 4px;
|
|
254
|
-
padding: 14px 16px;
|
|
132
|
+
.deployment-target-mark img {
|
|
133
|
+
width: 26px;
|
|
134
|
+
height: 26px;
|
|
135
|
+
object-fit: contain;
|
|
255
136
|
}
|
|
256
|
-
.
|
|
257
|
-
|
|
258
|
-
|
|
137
|
+
.deployment-target-mark.text-mark {
|
|
138
|
+
border-radius: 7px;
|
|
139
|
+
background: hsl(var(--muted));
|
|
140
|
+
font-size: 12px;
|
|
141
|
+
font-weight: 700;
|
|
259
142
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
143
|
+
@media (max-width: 640px) {
|
|
144
|
+
.deployment-target-grid {
|
|
145
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
146
|
+
}
|
|
264
147
|
}
|
|
265
148
|
```
|
|
266
149
|
|
|
267
150
|
</Diagram>
|
|
268
151
|
|
|
269
|
-
##
|
|
270
|
-
|
|
271
|
-
By default, Nitro builds for Node.js. To target a different platform, set the preset in your `vite.config.ts`:
|
|
272
|
-
|
|
273
|
-
```ts
|
|
274
|
-
import { agentNative } from "@agent-native/core/vite";
|
|
275
|
-
import { defineConfig } from "vite";
|
|
276
|
-
|
|
277
|
-
export default defineConfig({
|
|
278
|
-
plugins: [agentNative({ nitro: { preset: "vercel" } })],
|
|
279
|
-
});
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
Or use the `NITRO_PRESET` environment variable at build time:
|
|
283
|
-
|
|
284
|
-
```bash
|
|
285
|
-
NITRO_PRESET=netlify npx @agent-native/core@latest build
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
## Node.js (Default) {#nodejs}
|
|
289
|
-
|
|
290
|
-
The default preset. Build and run:
|
|
291
|
-
|
|
292
|
-
```bash
|
|
293
|
-
npx @agent-native/core@latest build
|
|
294
|
-
node .output/server/index.mjs
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
Set `PORT` to configure the listen port (default: `3000`).
|
|
298
|
-
|
|
299
|
-
Use the current Node.js LTS line for production deploys. As of May 2026, that
|
|
300
|
-
is Node.js 24; Node.js 20 reached end-of-life on April 30, 2026 and no longer
|
|
301
|
-
receives upstream security updates.
|
|
302
|
-
|
|
303
|
-
### Docker {#docker}
|
|
304
|
-
|
|
305
|
-
This Dockerfile works for the standalone app created above. Run `pnpm install` before building so `pnpm-lock.yaml` exists in the build context. Keep the dependency manifest and lockfile in sync when you update the app.
|
|
306
|
-
|
|
307
|
-
```dockerfile filename="Dockerfile"
|
|
308
|
-
FROM node:24-slim AS build
|
|
309
|
-
WORKDIR /app
|
|
310
|
-
COPY package.json pnpm-lock.yaml ./
|
|
311
|
-
RUN corepack enable && pnpm install --frozen-lockfile
|
|
312
|
-
COPY . .
|
|
313
|
-
RUN pnpm build
|
|
314
|
-
|
|
315
|
-
FROM node:24-slim
|
|
316
|
-
WORKDIR /app
|
|
317
|
-
COPY --from=build /app/.output .output
|
|
318
|
-
# data/ is a runtime-created SQLite directory — do not copy a dev DB into prod.
|
|
319
|
-
# For production, set DATABASE_URL to a hosted Postgres or Turso instance.
|
|
320
|
-
RUN mkdir -p /app/data
|
|
321
|
-
ENV NODE_ENV=production
|
|
322
|
-
ENV PORT=3000
|
|
323
|
-
EXPOSE 3000
|
|
324
|
-
CMD ["node", ".output/server/index.mjs"]
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
Create `.dockerignore` alongside the Dockerfile:
|
|
328
|
-
|
|
329
|
-
```text filename=".dockerignore"
|
|
330
|
-
node_modules
|
|
331
|
-
.output
|
|
332
|
-
data
|
|
333
|
-
.env
|
|
334
|
-
.env.*
|
|
335
|
-
!.env.example
|
|
336
|
-
.git
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
### Self-hosted workspace with Docker Compose {#workspace-docker-compose}
|
|
340
|
-
|
|
341
|
-
The Dockerfile above is for one standalone app. A workspace is not one Nitro
|
|
342
|
-
server process today: each app still builds to its own `.output/` directory and
|
|
343
|
-
runs its own Node/Nitro server. For a VPS, run one container per workspace app,
|
|
344
|
-
point every app at the same Postgres database and shared production secrets, and
|
|
345
|
-
put a reverse proxy in front that routes path prefixes (`/mail`, `/calendar`,
|
|
346
|
-
...) to the matching app container.
|
|
347
|
-
|
|
348
|
-
Build each app with the same base path that the proxy will use at runtime. The
|
|
349
|
-
base path is a build-time input for the client bundle and a runtime input for
|
|
350
|
-
the server:
|
|
351
|
-
|
|
352
|
-
```bash maxLines=8
|
|
353
|
-
APP_BASE_PATH=/mail VITE_APP_BASE_PATH=/mail npx @agent-native/core@latest build
|
|
354
|
-
node .output/server/index.mjs
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
A reusable workspace Dockerfile can take the app name and path prefix as build
|
|
358
|
-
arguments:
|
|
359
|
-
|
|
360
|
-
```dockerfile filename="Dockerfile.workspace-app" maxLines=12
|
|
361
|
-
FROM node:24-slim AS build
|
|
362
|
-
WORKDIR /workspace
|
|
363
|
-
RUN corepack enable
|
|
364
|
-
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
|
365
|
-
COPY packages ./packages
|
|
366
|
-
COPY apps ./apps
|
|
367
|
-
ARG APP_NAME
|
|
368
|
-
ARG APP_BASE_PATH
|
|
369
|
-
ENV APP_BASE_PATH=$APP_BASE_PATH
|
|
370
|
-
ENV VITE_APP_BASE_PATH=$APP_BASE_PATH
|
|
371
|
-
RUN pnpm install --frozen-lockfile
|
|
372
|
-
RUN pnpm --dir apps/$APP_NAME build
|
|
373
|
-
|
|
374
|
-
FROM node:24-slim
|
|
375
|
-
WORKDIR /app
|
|
376
|
-
ARG APP_NAME
|
|
377
|
-
ARG APP_BASE_PATH
|
|
378
|
-
ENV NODE_ENV=production
|
|
379
|
-
ENV PORT=3000
|
|
380
|
-
ENV APP_BASE_PATH=$APP_BASE_PATH
|
|
381
|
-
COPY --from=build /workspace/apps/$APP_NAME/.output .output
|
|
382
|
-
EXPOSE 3000
|
|
383
|
-
CMD ["node", ".output/server/index.mjs"]
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
Then compose Postgres, the app containers, and your proxy. This example uses
|
|
387
|
-
Caddy because it can terminate HTTP locally or sit behind Cloudflare's SSL
|
|
388
|
-
proxy, but the important part is the path-prefix routing:
|
|
389
|
-
|
|
390
|
-
```yaml filename="docker-compose.yml" maxLines=30
|
|
391
|
-
services:
|
|
392
|
-
postgres:
|
|
393
|
-
image: postgres:17
|
|
394
|
-
restart: unless-stopped
|
|
395
|
-
environment:
|
|
396
|
-
POSTGRES_DB: agent_native
|
|
397
|
-
POSTGRES_USER: agent_native
|
|
398
|
-
POSTGRES_PASSWORD: change-me
|
|
399
|
-
volumes:
|
|
400
|
-
- postgres-data:/var/lib/postgresql/data
|
|
401
|
-
|
|
402
|
-
mail:
|
|
403
|
-
build:
|
|
404
|
-
context: .
|
|
405
|
-
dockerfile: Dockerfile.workspace-app
|
|
406
|
-
args:
|
|
407
|
-
APP_NAME: mail
|
|
408
|
-
APP_BASE_PATH: /mail
|
|
409
|
-
restart: unless-stopped
|
|
410
|
-
environment:
|
|
411
|
-
DATABASE_URL: postgres://agent_native:change-me@postgres:5432/agent_native
|
|
412
|
-
BETTER_AUTH_URL: https://agents.example.com/mail
|
|
413
|
-
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
|
|
414
|
-
A2A_SECRET: ${A2A_SECRET}
|
|
415
|
-
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
|
416
|
-
depends_on:
|
|
417
|
-
- postgres
|
|
418
|
-
|
|
419
|
-
calendar:
|
|
420
|
-
build:
|
|
421
|
-
context: .
|
|
422
|
-
dockerfile: Dockerfile.workspace-app
|
|
423
|
-
args:
|
|
424
|
-
APP_NAME: calendar
|
|
425
|
-
APP_BASE_PATH: /calendar
|
|
426
|
-
restart: unless-stopped
|
|
427
|
-
environment:
|
|
428
|
-
DATABASE_URL: postgres://agent_native:change-me@postgres:5432/agent_native
|
|
429
|
-
BETTER_AUTH_URL: https://agents.example.com/calendar
|
|
430
|
-
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
|
|
431
|
-
A2A_SECRET: ${A2A_SECRET}
|
|
432
|
-
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
|
433
|
-
depends_on:
|
|
434
|
-
- postgres
|
|
435
|
-
|
|
436
|
-
proxy:
|
|
437
|
-
image: caddy:2
|
|
438
|
-
restart: unless-stopped
|
|
439
|
-
ports:
|
|
440
|
-
- "80:80"
|
|
441
|
-
- "443:443"
|
|
442
|
-
volumes:
|
|
443
|
-
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
444
|
-
depends_on:
|
|
445
|
-
- mail
|
|
446
|
-
- calendar
|
|
447
|
-
|
|
448
|
-
volumes:
|
|
449
|
-
postgres-data:
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
```caddyfile filename="Caddyfile"
|
|
453
|
-
agents.example.com {
|
|
454
|
-
reverse_proxy /mail* mail:3000
|
|
455
|
-
reverse_proxy /calendar* calendar:3000
|
|
456
|
-
}
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
Notes for this shape:
|
|
460
|
-
|
|
461
|
-
- Keep `DATABASE_URL`, `BETTER_AUTH_SECRET`, `A2A_SECRET`, and other production
|
|
462
|
-
secrets identical across app containers when you want shared auth, shared
|
|
463
|
-
credentials, and cross-app A2A.
|
|
464
|
-
- Set `BETTER_AUTH_URL` to the public URL for that app path. OAuth callback URLs
|
|
465
|
-
should use the same public URL.
|
|
466
|
-
- Do not rely on the container filesystem for production data; use Postgres (or
|
|
467
|
-
another persistent SQL backend) for `DATABASE_URL`.
|
|
468
|
-
- If Cloudflare terminates TLS in front of the VPS, configure Cloudflare to send
|
|
469
|
-
normal `X-Forwarded-Proto` / `X-Forwarded-Host` headers and route the public
|
|
470
|
-
host to the proxy container.
|
|
471
|
-
|
|
472
|
-
## Vercel {#vercel}
|
|
473
|
-
|
|
474
|
-
```ts filename="vite.config.ts"
|
|
475
|
-
export default defineConfig({
|
|
476
|
-
plugins: [agentNative({ nitro: { preset: "vercel" } })],
|
|
477
|
-
});
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
Deploy via the Vercel CLI or git push:
|
|
481
|
-
|
|
482
|
-
```bash
|
|
483
|
-
vercel deploy
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
For a workspace, build every app into one Vercel Build Output API bundle:
|
|
487
|
-
|
|
488
|
-
```bash
|
|
489
|
-
npx @agent-native/core@latest deploy --preset vercel
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
For Vercel Git deployments, set the build command to:
|
|
493
|
-
|
|
494
|
-
```bash
|
|
495
|
-
npx @agent-native/core@latest deploy --preset vercel --build-only
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
The workspace build copies each app's Nitro `vercel` output into the root `.vercel/output`, gives each function its own mount-path environment, and writes the route config that serves apps at `/<app-id>`.
|
|
499
|
-
|
|
500
|
-
## Netlify {#netlify}
|
|
501
|
-
|
|
502
|
-
The Nitro `netlify` preset works well and, in practice, has given us much faster cold starts than Cloudflare Pages (~200ms TTFB vs ~9s) for templates that talk to external Postgres (Neon). Either set the preset in `vite.config.ts`:
|
|
503
|
-
|
|
504
|
-
```ts filename="vite.config.ts"
|
|
505
|
-
export default defineConfig({
|
|
506
|
-
plugins: [agentNative({ nitro: { preset: "netlify" } })],
|
|
507
|
-
});
|
|
508
|
-
```
|
|
509
|
-
|
|
510
|
-
…or set `NITRO_PRESET=netlify` at build time.
|
|
511
|
-
|
|
512
|
-
For a workspace, deploy every app from one Netlify site by running:
|
|
513
|
-
|
|
514
|
-
```bash
|
|
515
|
-
npx @agent-native/core@latest deploy --preset netlify
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
The workspace build writes static assets under `dist/_workspace_static/` and routes each app to its own Netlify function without forced asset redirects, so files like `/mail/assets/...` are served statically before the server function handles app routes.
|
|
519
|
-
|
|
520
|
-
### Keep-warm and scale-to-zero databases {#netlify-keep-warm}
|
|
521
|
-
|
|
522
|
-
When enabled, the Netlify build emits a scheduled function that requests `/_agent-native/health` **every minute**. That keeps the server function and its database warm so the next visitor after an idle period doesn't pay a cold start (1–5s on Neon).
|
|
523
|
-
|
|
524
|
-
Keep-warm is **disabled by default** because a once-a-minute wake prevents autosuspend on metered scale-to-zero databases. On a free-tier Neon this can exhaust the compute quota, and the database then rejects **all** reads mid-session — the symptom is a dead app, not a slow one. Set `AGENT_NATIVE_ENABLE_KEEP_WARM=1` when the lower next-visitor latency is worth the database awake-time.
|
|
525
|
-
|
|
526
|
-
The keep-warm schedule and background-function warm only apply after the main keep-warm flag is enabled:
|
|
527
|
-
|
|
528
|
-
| Variable | Effect |
|
|
529
|
-
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
530
|
-
| `AGENT_NATIVE_ENABLE_KEEP_WARM` | Opts into the scheduled server/database warm. Unset by default. |
|
|
531
|
-
| `AGENT_NATIVE_DISABLE_KEEP_WARM` | Compatibility kill switch that wins over the opt-in flag when set. |
|
|
532
|
-
| `AGENT_NATIVE_KEEP_WARM_SCHEDULE` | Overrides the cadence with a 5-field cron expression, e.g. `*/5 * * * *`. The default cadence when enabled is `* * * * *`; an unparseable value **fails the build**. |
|
|
533
|
-
| `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND` | Drops only the background-function warm, keeping the server warm. Warming `server` is one request; warming `-background` starts a fresh container that re-probes the schema. |
|
|
534
|
-
|
|
535
|
-
If you are on a free or otherwise quota-limited database tier, leave `AGENT_NATIVE_ENABLE_KEEP_WARM` unset. If you opt in, use a slower cadence or set `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND=1` to drop the more expensive background warm.
|
|
536
|
-
|
|
537
|
-
### On-demand schema DDL {#skip-ensure-tables}
|
|
538
|
-
|
|
539
|
-
Each store calls `ensureTable()` on its first database touch, which probes
|
|
540
|
-
`information_schema` / `pg_indexes` and issues `CREATE TABLE` / `ADD COLUMN` /
|
|
541
|
-
`CREATE INDEX` only for what is genuinely missing. On a long-lived Node server
|
|
542
|
-
that cost is paid once per boot and is invisible. On serverless, "first touch" is
|
|
543
|
-
**every cold start**, across ~57 stores — so a cold request can pay a few hundred
|
|
544
|
-
serial round trips before it does any real work.
|
|
545
|
-
|
|
546
|
-
Two things reduce it:
|
|
547
|
-
|
|
548
|
-
- The probes are answered from **one batched introspection pass per database**
|
|
549
|
-
(two queries), instead of one query per table, column, and index. This is
|
|
550
|
-
automatic and needs no configuration.
|
|
551
|
-
- `AGENT_NATIVE_SKIP_ENSURE_TABLES=1` skips the probe-and-DDL machinery
|
|
552
|
-
altogether, which is the largest cold-start latency win available.
|
|
553
|
-
|
|
554
|
-
Set `AGENT_NATIVE_SKIP_ENSURE_TABLES=1` when your database schema is already
|
|
555
|
-
migrated and you do not want application boot creating or altering tables — the
|
|
556
|
-
normal case for a production deployment with a real migration step.
|
|
557
|
-
|
|
558
|
-
<Callout tone="risk">
|
|
559
|
-
|
|
560
|
-
**This flag does not and cannot fail closed.** If the schema is in fact missing, the first real query fails loudly rather than being repaired on the fly — which is the point, but it means you own the migration story. Do not set it on a deployment that relies on application boot to provision its tables.
|
|
561
|
-
|
|
562
|
-
</Callout>
|
|
563
|
-
|
|
564
|
-
## Cloudflare Pages {#cloudflare-pages}
|
|
565
|
-
|
|
566
|
-
```ts filename="vite.config.ts"
|
|
567
|
-
export default defineConfig({
|
|
568
|
-
plugins: [agentNative({ nitro: { preset: "cloudflare_pages" } })],
|
|
569
|
-
});
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
## Cloudflare Workers {#cloudflare-workers}
|
|
573
|
-
|
|
574
|
-
Use Nitro's native module output for a Cloudflare Worker. This keeps SSR
|
|
575
|
-
enabled and emits the Worker entry point plus static assets under
|
|
576
|
-
`.output/server` and `.output/public`:
|
|
577
|
-
|
|
578
|
-
```ts filename="vite.config.ts"
|
|
579
|
-
export default defineConfig({
|
|
580
|
-
plugins: [agentNative({ nitro: { preset: "cloudflare_module" } })],
|
|
581
|
-
});
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
Build and deploy the generated Worker with Wrangler:
|
|
585
|
-
|
|
586
|
-
```bash
|
|
587
|
-
npx @agent-native/core@latest build
|
|
588
|
-
npx wrangler deploy --config .output/server/wrangler.json
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
You can also select the preset explicitly with
|
|
592
|
-
`NITRO_PRESET=cloudflare_module`. Configure a durable external SQL database
|
|
593
|
-
before deploying; a Worker filesystem is not a persistent application store.
|
|
594
|
-
|
|
595
|
-
## AWS Lambda {#aws-lambda}
|
|
596
|
-
|
|
597
|
-
```ts filename="vite.config.ts"
|
|
598
|
-
export default defineConfig({
|
|
599
|
-
plugins: [agentNative({ nitro: { preset: "aws_lambda" } })],
|
|
600
|
-
});
|
|
601
|
-
```
|
|
602
|
-
|
|
603
|
-
## Deno Deploy {#deno-deploy}
|
|
604
|
-
|
|
605
|
-
```ts filename="vite.config.ts"
|
|
606
|
-
export default defineConfig({
|
|
607
|
-
plugins: [agentNative({ nitro: { preset: "deno_deploy" } })],
|
|
608
|
-
});
|
|
609
|
-
```
|
|
610
|
-
|
|
611
|
-
## SSR Caching {#ssr-caching}
|
|
612
|
-
|
|
613
|
-
Every SSR HTML response and every React Router `.data` response is one impersonal, public shell: `createH3SSRHandler` strips cookies before rendering, so the same bytes are correct for every visitor and all personalization happens on the client after load. That is what makes it safe to stamp a single hard-cache policy on those responses by default:
|
|
614
|
-
|
|
615
|
-
```txt
|
|
616
|
-
cache-control: public, max-age=600, stale-while-revalidate=604800, stale-if-error=3600
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
The same value is mirrored onto `cdn-cache-control` and `netlify-cdn-cache-control`. One shared CDN entry then serves the whole site instead of a per-request render, which is the single biggest lever on first-response latency — leave it on unless one of the cases below applies to your deployment.
|
|
620
|
-
|
|
621
|
-
### Overriding with `AGENT_NATIVE_SSR_CACHE` {#ssr-cache-env}
|
|
622
|
-
|
|
623
|
-
Set `AGENT_NATIVE_SSR_CACHE` in the deploy environment to change the policy for the whole deployment:
|
|
624
|
-
|
|
625
|
-
| Value | Result |
|
|
626
|
-
| --------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
627
|
-
| unset, `on`, `default`, `true`, `1` | The default policy above, unchanged. Recommended — best performance. |
|
|
628
|
-
| `off`, `false`, `0`, `none`, `no-store`, `disabled` | `no-store` on `cache-control`, `cdn-cache-control`, and `netlify-cdn-cache-control`. |
|
|
629
|
-
| A duration: `30`, `30s`, `5m`, `2h` | `public, max-age=<n>, stale-while-revalidate=<n>, stale-if-error=3600`. |
|
|
630
|
-
|
|
631
|
-
Bare numbers are seconds. `stale-while-revalidate` deliberately mirrors `max-age` for a custom duration: a short freshness window paired with the default seven-day stale window would hand back exactly the staleness you opted out of. An unrecognized value logs a warning and falls back to the default, so a typo can never silently disable the CDN.
|
|
632
|
-
|
|
633
|
-
Turn it down or off when either of these is true:
|
|
634
|
-
|
|
635
|
-
1. **Your host does not purge its CDN on deploy.** Netlify and Vercel do; some self-managed setups do not. Without a purge, a shipped build can keep serving the previous shell for `max-age` plus `stale-while-revalidate`.
|
|
636
|
-
2. **Your loaders return mutable public data.** After a successful mutation, a `useRevalidator()` or redirect-after-action re-fetch can read the browser's cached `.data` copy instead of fresh loader output.
|
|
637
|
-
|
|
638
|
-
The setting applies to every public-shell surface: React Router SSR HTML and `.data`, the login HTML shell, the `/_agent-native/speculation-rules.json` route, the docs site, and the public-form SSR in the forms template. The generated Cloudflare Worker resolves it at build time, so set it in the deploy environment before the build runs.
|
|
639
|
-
|
|
640
|
-
Three things to keep in mind:
|
|
641
|
-
|
|
642
|
-
- **Turning caching off does not make SSR personalized.** Cookies are still stripped before render and SSR loaders still see the anonymous branch. Per-user data must still be resolved client-side. This variable controls cache _duration_ only.
|
|
643
|
-
- **It is deployment-wide, not per-route, by design.** A per-route or per-request cache override is how one visitor's payload ends up in another visitor's shared CDN entry, so the framework does not offer one — `guard:ssr-cache-shell` enforces it.
|
|
644
|
-
- **For mutation-fresh data, prefer actions over disabling the cache.** App data belongs in [actions](/docs/actions-overview), read from the client with `useActionQuery` / `useActionMutation` and kept live by `useDbSync()` polling; none of that goes through the SSR shell cache. Keep SSR loaders rendering the public shell, and reach for this variable only when you genuinely want loader data fresher.
|
|
645
|
-
|
|
646
|
-
## Environment Variables {#environment-variables}
|
|
647
|
-
|
|
648
|
-
For the repository-wide reference, including template, provider, local, and CI
|
|
649
|
-
variables, see [Environment Variables](/docs/environment-variables). The tables
|
|
650
|
-
below remain the authoritative deployment guide for production values and
|
|
651
|
-
hosting behavior.
|
|
652
|
-
|
|
653
|
-
### Build / Runtime {#env-runtime}
|
|
654
|
-
|
|
655
|
-
| Variable | Description |
|
|
656
|
-
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
657
|
-
| `PORT` | Server port (Node.js only) |
|
|
658
|
-
| `NITRO_PRESET` | Override build preset at build time |
|
|
659
|
-
| `APP_BASE_PATH` | Mount the app under a prefix (e.g. `/mail`). Set automatically by `npx @agent-native/core@latest deploy`; leave unset for standalone. |
|
|
660
|
-
| `APP_URL` | Optional canonical public origin. Checked ahead of `BETTER_AUTH_URL` when resolving the A2A JWT audience, the OAuth public origin, self-dispatch webhook targets, and generated resource links. Set it explicitly on preview/staging deploys where the request host is unreliable. |
|
|
661
|
-
| `AGENT_PROD_CODE_EXECUTION` | Optional production code-execution mode: `off` (default), `sandboxed`, or `trusted`. See [Production Code Execution](#production-code-execution). |
|
|
662
|
-
| `AGENT_NATIVE_SSR_CACHE` | Deployment-wide SSR shell cache policy: unset/`on` keeps the default hard-cache, `off` sends `no-store`, or a duration such as `30s` / `5m` sets a shorter freshness. See [SSR Caching](#ssr-caching). |
|
|
663
|
-
| `AGENT_NATIVE_ENABLE_KEEP_WARM` | Opt into the Netlify keep-warm scheduled function. Unset by default; see [Keep-warm](#netlify-keep-warm). |
|
|
664
|
-
| `AGENT_NATIVE_DISABLE_KEEP_WARM` | Compatibility kill switch for the Netlify keep-warm scheduled function. See [Keep-warm](#netlify-keep-warm). |
|
|
665
|
-
| `AGENT_NATIVE_KEEP_WARM_SCHEDULE` | Override the keep-warm cadence with a 5-field cron expression (default `* * * * *` when enabled). An unparseable value fails the build. See [Keep-warm](#netlify-keep-warm). |
|
|
666
|
-
| `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND` | Drop only the background-function warm and keep the server warm. See [Keep-warm](#netlify-keep-warm). |
|
|
667
|
-
| `AGENT_NATIVE_DISABLE_INPROCESS_SWEEPS` | Turn off the in-process backstop sweep timers (automation redispatch, agent-teams reconciliation, sandbox-execution recovery). On serverless these run per warm container, so their query rate scales with instance count. Set it **only** where a durable scheduler already drives the same recovery, or queued work will not be retried. |
|
|
668
|
-
| `AGENT_NATIVE_SKIP_ENSURE_TABLES` | Skip on-demand schema DDL entirely. Removes the schema-probe round trips every cold start pays before doing any work. Requires that your schema is already migrated — see [On-demand schema DDL](#skip-ensure-tables). |
|
|
669
|
-
| `AGENT_NATIVE_BUILDER_RELAY_SECRET` | Dedicated 32+ char shared HMAC secret for preview-safe Builder authorization relay. Set the same value on the approved corporate callback deployment and preview deployments only when authorization must land in an isolated preview database. |
|
|
670
|
-
| `AGENT_NATIVE_BUILDER_RELAY_TARGET_ORIGINS` | Corporate callback-only, comma-separated allowlist of exact trusted preview origins (for example, `https://0123456789abcdef01234567--content.netlify.app`). Set it only on the corporate callback deployment. Netlify origins must use an immutable, deploy-specific 24-hex permalink; mutable `deploy-preview-*` aliases, wildcards, and domain suffixes are rejected. |
|
|
671
|
-
|
|
672
|
-
Database connection variables (`DATABASE_URL`, `DATABASE_AUTH_TOKEN`, per-app `<APP_NAME>_DATABASE_URL`) live in [Database](/docs/database#production).
|
|
673
|
-
|
|
674
|
-
### Production-sensitive configuration {#env-required-prod}
|
|
675
|
-
|
|
676
|
-
These settings cover production-sensitive behavior. A standalone app using the
|
|
677
|
-
framework auth needs a stable `BETTER_AUTH_SECRET` and a persistent database;
|
|
678
|
-
the public auth URL is inferred from the request, known template, or hosting
|
|
679
|
-
platform when it is unset. Workspace and A2A settings are conditional on those
|
|
680
|
-
features. Missing values either fail-closed or fall back to weaker behavior
|
|
681
|
-
with a loud warning.
|
|
682
|
-
|
|
683
|
-
| Variable | Description |
|
|
684
|
-
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
685
|
-
| `BETTER_AUTH_SECRET` | 32+ char random string. Signs session cookies and is the fallback for `OAUTH_STATE_SECRET` and app-local encrypted values. It is also a legacy read candidate for existing shared vault ciphertext. Hard-required: the framework throws on startup if missing in production. |
|
|
686
|
-
| `BETTER_AUTH_URL` | Optional public origin override for this app (e.g. `https://mail.example.com`). The framework infers it from request, known-template, and hosting-platform context when unset. |
|
|
687
|
-
| `ANTHROPIC_API_KEY` | API key for the embedded production agent. **In multi-tenant deploys**, the framework refuses to fall back to this when the user has no per-user key — bring-your-own-key is required. Single-tenant self-hosted installs use it as a global key. |
|
|
688
|
-
| `OAUTH_STATE_SECRET` | Dedicated HMAC key for OAuth state envelopes (Google, Atlassian, Zoom). Falls back to `BETTER_AUTH_SECRET` when unset, but a dedicated value is recommended so rotating one doesn't invalidate the other. Generate via `openssl rand -hex 32`. |
|
|
689
|
-
| `A2A_SECRET` | Shared HMAC for inter-app A2A JSON-RPC and signed background handoffs. Required for hosted workspace deploys and A2A features; without it, those endpoints fail closed in production. When no dedicated workspace vault key is set, shared vault ciphertext uses a purpose-derived key from this value, so rotating it also rotates the vault key. |
|
|
690
|
-
| `WORKSPACE_SECRETS_ENCRYPTION_KEY` | Preferred stable AES-256-GCM key for the shared encrypted-at-rest secrets vault. Set the same value in every app that reads the vault. It is separate from app-local OAuth/credential encryption, so A2A trust can rotate without stranding vault rows. Existing A2A-, Better Auth-, and app-key ciphertext is migrated on successful reads. |
|
|
691
|
-
| `WORKSPACE_SECRETS_ENCRYPTION_KEY_PREVIOUS` | Optional previous workspace vault key used only during a rotation window. Deploy it alongside the new `WORKSPACE_SECRETS_ENCRYPTION_KEY`, let successful reads re-encrypt rows, then remove it after migration. |
|
|
692
|
-
| `SECRETS_ENCRYPTION_KEY` | Legacy combined key for app-local encryption and the shared vault. It remains supported, but new multi-app deployments should use `WORKSPACE_SECRETS_ENCRYPTION_KEY` for the shared vault so changing workspace encryption does not change app-local OAuth ciphertext. |
|
|
693
|
-
|
|
694
|
-
### Auth & Identity {#env-auth}
|
|
695
|
-
|
|
696
|
-
OAuth provider credentials (Google, GitHub), static MCP bearer fallbacks (`ACCESS_TOKEN` / `ACCESS_TOKENS`), and email-verification toggles are documented in [Authentication](/docs/authentication). Set them there per the auth mode you choose.
|
|
697
|
-
|
|
698
|
-
### Inbound Webhooks {#env-webhooks}
|
|
699
|
-
|
|
700
|
-
Each messaging integration requires its own signing secret in production (handlers fail-closed on forged requests when the secret is missing). The per-integration variables are listed in [Messaging](/docs/messaging) and [Security](/docs/security). For local development only, `AGENT_NATIVE_ALLOW_UNVERIFIED_WEBHOOKS=1` opts back into "warn and accept" — never set it in prod.
|
|
701
|
-
|
|
702
|
-
### Security Configuration (Opt-in) {#security-config}
|
|
703
|
-
|
|
704
|
-
Defaults are strict. A handful of opt-in flags relax behavior (debug stack traces, unverified webhooks, workspace-scoped key fallback, the MCP hub multi-org switch, runtime env-var writes). They are documented with their security trade-offs in [Security](/docs/security). Don't set them unless you specifically want the relaxed path.
|
|
705
|
-
|
|
706
|
-
### Workspace .env Inheritance {#env-inheritance}
|
|
707
|
-
|
|
708
|
-
Inside a workspace, the root `.env` is loaded into every app automatically, so shared keys like `ANTHROPIC_API_KEY`, `A2A_SECRET`, `BETTER_AUTH_SECRET`, and `OAUTH_STATE_SECRET` only need to be set once. Per-app `apps/<name>/.env` wins on conflict.
|
|
709
|
-
|
|
710
|
-
### Generating Strong Secrets {#env-generate-secrets}
|
|
711
|
-
|
|
712
|
-
For any secret marked "32+ char random" (`BETTER_AUTH_SECRET`, `OAUTH_STATE_SECRET`, `A2A_SECRET`, `WORKSPACE_SECRETS_ENCRYPTION_KEY`, `SECRETS_ENCRYPTION_KEY`, `AGENT_NATIVE_BUILDER_RELAY_SECRET`), generate fresh values with:
|
|
713
|
-
|
|
714
|
-
```bash
|
|
715
|
-
openssl rand -hex 32
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
Rotate signing/session keys by replacing the env var on every instance and redeploying — sessions / OAuth state envelopes signed under the old key become invalid, so users may need to sign in again. Rotate `WORKSPACE_SECRETS_ENCRYPTION_KEY` with the `..._PREVIOUS` window described above so encrypted vault rows remain readable while they migrate.
|
|
719
|
-
|
|
720
|
-
## Production Agent Tools {#production-agent-tools}
|
|
721
|
-
|
|
722
|
-
Production agents get the app's registered actions plus the framework's own
|
|
723
|
-
tools. `frameworkTools` selects which of those framework tools this app exposes.
|
|
724
|
-
Every group defaults to today's behavior, so omitting the option changes
|
|
725
|
-
nothing:
|
|
726
|
-
|
|
727
|
-
```ts filename="server/plugins/agent-chat.ts"
|
|
728
|
-
export default createAgentChatPlugin({
|
|
729
|
-
frameworkTools: {
|
|
730
|
-
database: "read", // "write" | "read" | "off" — default "read"
|
|
731
|
-
extensions: true, // default false
|
|
732
|
-
sharing: false, // this app has no share surface
|
|
733
|
-
review: false,
|
|
734
|
-
},
|
|
735
|
-
});
|
|
736
|
-
```
|
|
737
|
-
|
|
738
|
-
```ts filename="server/plugins/core-routes.ts"
|
|
739
|
-
export default createCoreRoutesPlugin({
|
|
740
|
-
extensionTools: true,
|
|
741
|
-
});
|
|
742
|
-
```
|
|
743
|
-
|
|
744
|
-
`database` and `extensions` accept the values the old top-level flags did:
|
|
745
|
-
|
|
746
|
-
- `database: "read"` — default. Registers only `db-schema` and `db-query`;
|
|
747
|
-
agents inspect data with SQL but must use typed app actions for writes.
|
|
748
|
-
- `database: "write"` or `true` — additionally registers `db-exec` and
|
|
749
|
-
`db-patch` for deliberate raw SQL maintenance. Writes are scoped to the
|
|
750
|
-
current user/org and schema changes are blocked.
|
|
751
|
-
- `database: "off"` or `false` — removes raw database tools from the
|
|
752
|
-
agent surface so the app's actions are the only data access path.
|
|
753
|
-
- `extensions: true` — opts the app into framework extension-management
|
|
754
|
-
actions and prompt guidance (`create-extension`, `update-extension`, etc.).
|
|
755
|
-
Set `extensionTools: true` on the core-routes plugin as well to allow
|
|
756
|
-
authenticated REST creation. Extensions are disabled by default.
|
|
757
|
-
|
|
758
|
-
The remaining groups are booleans, all on by default: `sharing`, `review`,
|
|
759
|
-
`history`, `featureFlags`, `localization`, `audit`, `contextXray`,
|
|
760
|
-
`userProfile`, `automation`, `docs`, `resources`, `web`, `workspaceApps`,
|
|
761
|
-
`chat`, and `email`. Use `frameworkTools: "minimal"` to turn every group off at
|
|
762
|
-
once for a voice-first or single-purpose app, or
|
|
763
|
-
`frameworkTools: { preset: "minimal", resources: true }` to keep just one — an
|
|
764
|
-
explicit group key always wins over the preset.
|
|
765
|
-
|
|
766
|
-
Switching a group off removes it from the **agent** surfaces only: interactive
|
|
767
|
-
chat, MCP, A2A, and background runs. The matching HTTP action routes stay
|
|
768
|
-
mounted, because the UI reaches them through client hooks — disabling `sharing`
|
|
769
|
-
must not 404 a share dialog that is still on screen. Weigh that parity cost
|
|
770
|
-
before using it: the framework's contract is that anything the UI can do the
|
|
771
|
-
agent can do, so `sharing: false` alongside a visible share button is a
|
|
772
|
-
deliberate break, and only makes sense when the app has no such surface at all.
|
|
773
|
-
|
|
774
|
-
Framework tools are no longer promoted into the first model request by default,
|
|
775
|
-
independent of this option. They stay in the searchable registry and load
|
|
776
|
-
through `tool-search`, or immediately if the app names them in
|
|
777
|
-
`initialToolNames`.
|
|
778
|
-
|
|
779
|
-
<Callout tone="warning">
|
|
780
|
-
The top-level `databaseTools` and `extensionTools` options are deprecated in
|
|
781
|
-
favor of `frameworkTools.database` and `frameworkTools.extensions`. They are
|
|
782
|
-
still honored, but setting a top-level flag and its `frameworkTools`
|
|
783
|
-
equivalent to conflicting values throws at plugin startup rather than booting
|
|
784
|
-
with a tool surface nobody chose.
|
|
785
|
-
</Callout>
|
|
786
|
-
|
|
787
|
-
## Production Code Execution {#production-code-execution}
|
|
788
|
-
|
|
789
|
-
By default, production agents run without code-execution tools. They can call app actions, database tools, MCP tools, browser/session tools, and other registered framework tools, but they do not get shell or filesystem access.
|
|
790
|
-
|
|
791
|
-
Node-compatible deployments can opt into production code execution through the agent chat plugin or an environment override:
|
|
792
|
-
|
|
793
|
-
```ts filename="server/plugins/agent-chat.ts"
|
|
794
|
-
export default createAgentChatPlugin({
|
|
795
|
-
codeExecution: { production: "sandboxed" },
|
|
796
|
-
});
|
|
797
|
-
```
|
|
798
|
-
|
|
799
|
-
The available modes are:
|
|
800
|
-
|
|
801
|
-
- `off` — the default. No code-execution tools are registered in production.
|
|
802
|
-
- `sandboxed` — registers `run-code`, an isolated Node.js JavaScript runner with a scrubbed environment, a fresh temp directory, output/time limits, and a localhost bridge to allowlisted registered tools such as `provider-api-request`, `provider-api-docs`, `provider-api-catalog`, `web-request`, and the Resources-backed workspace file bridge used by `workspaceRead` / `workspaceWrite`.
|
|
803
|
-
- `trusted` — registers `run-code` plus the full coding tool registry (`bash`, `read`, `edit`, `write`). Use this only for single-tenant or operator-controlled deployments where full shell access to the host is intentional.
|
|
804
|
-
|
|
805
|
-
Set `AGENT_PROD_CODE_EXECUTION=sandboxed` or `AGENT_PROD_CODE_EXECUTION=trusted` to override the plugin option for a specific deployment without a code change. `AGENT_PROD_CODE_EXECUTION=off` forces code execution off even when the plugin option enables it.
|
|
806
|
-
|
|
807
|
-
The `run-code` sandbox is process-level isolation, not an OS container. It strips app secrets from the child process environment and uses the Node permission model when available, but outbound network is not blocked by Node itself; authenticated calls should go through the bridge helpers the tool exposes.
|
|
808
|
-
|
|
809
|
-
## Updating UI in Production {#updating-ui-in-production}
|
|
810
|
-
|
|
811
|
-
The ordinary deployed app agent works through app tools — actions, database,
|
|
812
|
-
MCP, and configured integrations — rather than receiving ambient access to the
|
|
813
|
-
app's source code. Source changes belong in the repository's development
|
|
814
|
-
workflow. An embedded, local, or Builder frame can edit the repository when
|
|
815
|
-
that frame is intentionally granted workspace and write tooling.
|
|
816
|
-
|
|
817
|
-
In a standard production deployment with [production code execution](#production-code-execution) left off, the agent has access to app tools (actions, database, MCP) but not the filesystem. This means the agent can read and write data, run actions, and interact with external services — but it can't edit your React components or add new routes on a deployed instance.
|
|
818
|
-
|
|
819
|
-
### Builder.io: Visual Editing in Production {#builderio}
|
|
820
|
-
|
|
821
|
-
[Builder.io](https://www.builder.io?utm_source=agent-native&utm_medium=docs&utm_campaign=framework&utm_content=deployment) is a separate managed code-capable workflow where an agent can modify your app's UI in production. Connect your repo to Builder.io (free tier available) and prompt for UI changes directly — no redeploy needed.
|
|
822
|
-
|
|
823
|
-
**Connect Builder** in Settings uses Builder OAuth (`builder:ai:invoke`) with a same-origin HTTPS callback under `/_agent-native/builder/callback`, so hosted origins such as Railway work without a domain allowlist. Legacy `BUILDER_*` private keys remain a runtime fallback for existing connections.
|
|
824
|
-
|
|
825
|
-
**How it works:**
|
|
152
|
+
## Advanced deployment
|
|
826
153
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
3. Prompt the agent to make UI changes — it edits your components, routes, and styles live
|
|
830
|
-
4. Changes are committed back to your repo
|
|
154
|
+
Start with the path above. Use these pages when you need provider-specific
|
|
155
|
+
settings or production controls:
|
|
831
156
|
|
|
832
|
-
|
|
157
|
+
- [**Node.js & Docker**](/docs/node-docker) - run the default preset directly or in a container
|
|
158
|
+
- [**Vercel**](/docs/vercel), [**Netlify**](/docs/netlify), and [**Cloudflare**](/docs/cloudflare) - configure the main hosted targets
|
|
159
|
+
- [**Other Platforms**](/docs/other-platforms) - deploy to AWS Lambda or Deno Deploy
|
|
160
|
+
- [**SSR Caching**](/docs/ssr-caching) - configure the public shell cache
|
|
161
|
+
- [**Deployment Environment Variables**](/docs/deployment-environment-variables) - production secrets, runtime flags, and workspace inheritance
|
|
162
|
+
- [**Production Agent Access**](/docs/actions-agent-tools) - control framework tools and code execution
|
|
163
|
+
- [**Updating UI in Production**](/docs/updating-ui-in-production) - understand the managed visual-editing workflow
|
|
833
164
|
|
|
834
|
-
|
|
165
|
+
<a id="self-host-quickstart"></a>
|
|
166
|
+
<a id="skip-ensure-tables"></a>
|
|
835
167
|
|
|
836
|
-
|
|
168
|
+
For compatibility with older links, the local Docker quickstart now lives on
|
|
169
|
+
[Node.js & Docker](/docs/node-docker#self-host-quickstart). Schema setup and
|
|
170
|
+
cold-start guidance live in the [deployment environment reference](/docs/deployment-environment-variables#skip-ensure-tables).
|
|
837
171
|
|
|
838
172
|
## What's next
|
|
839
173
|
|
|
840
|
-
- [**
|
|
841
|
-
- [**
|
|
842
|
-
- [**
|
|
843
|
-
- [**
|
|
844
|
-
- [**
|
|
845
|
-
- [**Public Agent Web**](/docs/agent-web-surfaces) — the `robots.txt`, `llms.txt`, and markdown-mirror files a Vite build writes into the deploy output for public routes
|
|
174
|
+
- [**Deploy an app**](/docs/deploy-an-app)
|
|
175
|
+
- [**Deploy a workspace**](/docs/workspace-deployment)
|
|
176
|
+
- [**Database**](/docs/server-database#production)
|
|
177
|
+
- [**Security**](/docs/security)
|
|
178
|
+
- [**Authentication**](/docs/authentication)
|