@agent-native/core 0.164.1 → 0.164.4

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 (56) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/app/components/agents/FeatureFlagsFleetPanel.tsx +78 -19
  3. package/corpus/templates/analytics/app/lib/use-auto-focus-select.ts +4 -4
  4. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -0
  5. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +6 -0
  6. package/corpus/templates/analytics/app/routes/_index.tsx +3 -2
  7. package/corpus/templates/analytics/app/routes/adhoc.$id.tsx +7 -2
  8. package/corpus/templates/analytics/app/routes/dashboard.tsx +3 -2
  9. package/corpus/templates/analytics/app/routes/overview.tsx +3 -2
  10. package/corpus/templates/analytics/app/routes/traffic.tsx +3 -2
  11. package/corpus/templates/analytics/changelog/2026-08-18-verify-cross-app-feature-flag-changes.md +6 -0
  12. package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +196 -48
  13. package/corpus/templates/analytics/server/plugins/feature-flags.ts +5 -0
  14. package/corpus/templates/analytics/shared/feature-flags.ts +10 -0
  15. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +5 -1
  16. package/corpus/templates/assets/app/routes/brand-kits._index.tsx +4 -1
  17. package/corpus/templates/assets/app/routes/libraries.tsx +4 -1
  18. package/corpus/templates/assets/app/routes/picker.tsx +4 -1
  19. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +1 -1
  20. package/corpus/templates/clips/app/routes/_app.wispr.tsx +2 -1
  21. package/corpus/templates/clips/app/routes/_index.tsx +7 -11
  22. package/corpus/templates/clips/app/routes/share.$shareId.tsx +3 -0
  23. package/corpus/templates/clips/changelog/2026-08-19-social-preview-video-frames.md +5 -0
  24. package/corpus/templates/clips/server/lib/slack-unfurls.ts +7 -13
  25. package/corpus/templates/clips/shared/share-meta.ts +67 -3
  26. package/corpus/templates/content/actions/list-content-databases.ts +95 -1
  27. package/corpus/templates/content/changelog/2026-08-11-content-mutations-delegated-from-verified-slack-dms-now-use-.md +6 -0
  28. package/corpus/templates/content/shared/api.ts +11 -0
  29. package/corpus/templates/design/app/routes/examples.tsx +2 -1
  30. package/corpus/templates/forms/app/routes/_index.tsx +3 -2
  31. package/corpus/templates/mail/app/routes/_index.tsx +3 -2
  32. package/corpus/templates/tasks/app/routes/_index.tsx +2 -1
  33. package/dist/a2a/artifact-response.d.ts +50 -0
  34. package/dist/a2a/artifact-response.js +266 -39
  35. package/dist/a2a/index.d.ts +2 -0
  36. package/dist/a2a/index.js +1 -0
  37. package/dist/cli/code-agent-executor.js +1 -1
  38. package/dist/deploy/build.js +10 -4
  39. package/dist/integrations/adapters/slack.js +58 -7
  40. package/dist/resources/handlers.d.ts +1 -1
  41. package/dist/server/agent-chat/action-filters-a2a.d.ts +2 -1
  42. package/dist/server/agent-chat/action-filters-a2a.js +10 -2
  43. package/dist/server/agent-chat-plugin.js +33 -11
  44. package/dist/server/realtime-token.d.ts +1 -1
  45. package/dist/server/ssr-handler.js +13 -4
  46. package/dist/shared/cache-control.d.ts +22 -0
  47. package/dist/shared/cache-control.js +25 -0
  48. package/dist/shared/index.d.ts +1 -0
  49. package/dist/shared/index.js +1 -0
  50. package/docs/content/drop-in-agent.mdx +4 -4
  51. package/docs/content/faq.mdx +15 -15
  52. package/docs/content/getting-started.mdx +173 -41
  53. package/docs/content/key-concepts.mdx +10 -10
  54. package/docs/content/using-your-agent.mdx +2 -2
  55. package/docs/content/what-is-agent-native.mdx +79 -228
  56. package/package.json +1 -1
@@ -199,17 +199,19 @@ export function createSerializedA2ATaskStatusWriter(taskId, writeStatus = update
199
199
  const A2A_ACTIVITY_CHECKPOINT_MIN_INTERVAL_MS = 2_000;
200
200
  export async function resolveA2ARecoverableArtifactSecret(orgId = getRequestOrgId()) {
201
201
  const globalSecret = process.env.A2A_SECRET?.trim();
202
- if (globalSecret)
203
- return globalSecret;
204
- if (!orgId)
205
- return undefined;
206
- try {
207
- const { getOrgA2ASecret } = await import("../org/context.js");
208
- return (await getOrgA2ASecret(orgId))?.trim() || undefined;
209
- }
210
- catch {
211
- return undefined;
202
+ if (orgId) {
203
+ try {
204
+ const { getOrgA2ASecret } = await import("../org/context.js");
205
+ const orgSecret = (await getOrgA2ASecret(orgId))?.trim();
206
+ if (orgSecret)
207
+ return orgSecret;
208
+ // coercion-ok: undefined is the fail-closed result when organization secret lookup throws
209
+ }
210
+ catch {
211
+ return undefined;
212
+ }
212
213
  }
214
+ return globalSecret || undefined;
213
215
  }
214
216
  export function buildLeanRunPolicyPrompt(codeEditingSurfaceRestriction, prodCodeExecPromptNote) {
215
217
  return codeEditingSurfaceRestriction + prodCodeExecPromptNote;
@@ -1619,6 +1621,7 @@ export function createAgentChatPlugin(options) {
1619
1621
  baseUrl: artifactBaseUrl,
1620
1622
  includePersistedArtifactMarker: true,
1621
1623
  persistedArtifactSecret: recoverableArtifactSecret,
1624
+ delegatedTaskId: context.taskId,
1622
1625
  })
1623
1626
  : null;
1624
1627
  if (recoverableArtifactText &&
@@ -1723,7 +1726,12 @@ export function createAgentChatPlugin(options) {
1723
1726
  };
1724
1727
  return;
1725
1728
  }
1726
- const { responseText, finalText } = assembleA2AFinalResponse(a2aEvents, a2aToolResults, { event: context.event, outcome: a2aOutcome });
1729
+ const { responseText, finalText, mutationReceipts } = assembleA2AFinalResponse(a2aEvents, a2aToolResults, {
1730
+ event: context.event,
1731
+ outcome: a2aOutcome,
1732
+ persistedArtifactSecret: recoverableArtifactSecret,
1733
+ delegatedTaskId: context.taskId,
1734
+ });
1727
1735
  console.log(`[A2A] Loop complete. Text: ${responseText.slice(0, 100)}...`);
1728
1736
  // Yield the final accumulated text
1729
1737
  yield {
@@ -1734,6 +1742,18 @@ export function createAgentChatPlugin(options) {
1734
1742
  type: "text",
1735
1743
  text: finalText,
1736
1744
  },
1745
+ ...(mutationReceipts.length > 0
1746
+ ? [
1747
+ {
1748
+ type: "data",
1749
+ data: {
1750
+ kind: "agent-native/mutation-receipts",
1751
+ version: 1,
1752
+ receipts: mutationReceipts,
1753
+ },
1754
+ },
1755
+ ]
1756
+ : []),
1737
1757
  ],
1738
1758
  };
1739
1759
  },
@@ -2000,8 +2020,10 @@ export function createAgentChatPlugin(options) {
2000
2020
  delegation: { protocol: "mcp" },
2001
2021
  },
2002
2022
  });
2023
+ const persistedArtifactSecret = await resolveA2ARecoverableArtifactSecret();
2003
2024
  return assembleA2AFinalResponse(mcpEvents, mcpToolResults, {
2004
2025
  outcome: mcpOutcome,
2026
+ persistedArtifactSecret,
2005
2027
  }).finalText;
2006
2028
  },
2007
2029
  });
@@ -26,8 +26,8 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
26
26
  expiresAt?: undefined;
27
27
  ttlSeconds?: undefined;
28
28
  } | {
29
- error?: undefined;
30
29
  token: string;
31
30
  expiresAt: string;
32
31
  ttlSeconds: number;
32
+ error?: undefined;
33
33
  }>>;
@@ -18,7 +18,7 @@ import { defineEventHandler } from "h3";
18
18
  */
19
19
  import { createRequestHandler } from "react-router";
20
20
  import { isMcpPublicPath } from "../mcp/route-paths.js";
21
- import { DEFAULT_SPECULATION_RULES_PATH, resolveSsrCacheHeaders, resolveSsrCacheKeyHeaders, } from "../shared/cache-control.js";
21
+ import { DEFAULT_SPECULATION_RULES_PATH, resolveSsrCacheHeaders, resolveSsrCacheKeyHeaders, SSR_QUERY_CACHE_KEY_HEADER, } from "../shared/cache-control.js";
22
22
  import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, withAgentNativeSocialImageCacheBuster, } from "../shared/social-meta.js";
23
23
  import { getAppBasePathFromViteEnv, stripAppBasePath as canonicalStripAppBasePath, } from "./app-base-path.js";
24
24
  import { getAppOriginClientConfigScript } from "./app-origin-config.js";
@@ -204,6 +204,8 @@ function isSsrHtmlOrDataResponse(headers, status, pathname) {
204
204
  * that contradicts that.
205
205
  */
206
206
  function applyDefaultSsrCacheHeader(headers, status, pathname) {
207
+ const varyByQuery = headers.get(SSR_QUERY_CACHE_KEY_HEADER)?.trim().toLowerCase() === "query";
208
+ headers.delete(SSR_QUERY_CACHE_KEY_HEADER);
207
209
  if (!isSsrHtmlOrDataResponse(headers, status, pathname))
208
210
  return;
209
211
  // A public shell must never set a viewer cookie or vary by credentials.
@@ -234,9 +236,16 @@ function applyDefaultSsrCacheHeader(headers, status, pathname) {
234
236
  for (const [name, value] of Object.entries(resolveSsrCacheHeaders())) {
235
237
  headers.set(name, value);
236
238
  }
237
- for (const [name, value] of Object.entries(resolveSsrCacheKeyHeaders())) {
238
- headers.set(name, value);
239
- }
239
+ const cacheKeyHeaders = resolveSsrCacheKeyHeaders();
240
+ const netlifyVary = varyByQuery
241
+ ? cacheKeyHeaders["netlify-vary"]
242
+ ? "query"
243
+ : undefined
244
+ : cacheKeyHeaders["netlify-vary"];
245
+ if (netlifyVary)
246
+ headers.set("netlify-vary", netlifyVary);
247
+ else
248
+ headers.delete("netlify-vary");
240
249
  }
241
250
  function applyDefaultSpeculationRulesHeader(headers, status, basePath) {
242
251
  if (status < 200 || status >= 400)
@@ -7,6 +7,28 @@ export declare const DEFAULT_SSR_CACHE_HEADERS: {
7
7
  readonly "cdn-cache-control": "public, max-age=600, stale-while-revalidate=604800, stale-if-error=3600";
8
8
  readonly "netlify-cdn-cache-control": "public, durable, s-maxage=31536000, stale-while-revalidate=604800, stale-if-error=3600";
9
9
  };
10
+ /**
11
+ * Content type used by impersonal HTML redirects that should enter the
12
+ * deployment adapter's shared SSR cache path.
13
+ */
14
+ export declare const SSR_HTML_CONTENT_TYPE = "text/html; charset=utf-8";
15
+ /**
16
+ * Internal response marker for public HTML whose redirect target preserves
17
+ * request query parameters. The SSR adapters consume this marker and emit a
18
+ * provider-specific full-query cache key only where the provider supports it.
19
+ */
20
+ export declare const SSR_QUERY_CACHE_KEY_HEADER = "x-agent-native-ssr-key";
21
+ export type SsrHtmlContentTypeOptions = {
22
+ varyByQuery?: boolean;
23
+ };
24
+ /**
25
+ * Mark an already-built HTML response as HTML without changing its redirect
26
+ * status, location, or other headers. Only use this for redirects whose
27
+ * target is independent of the viewer and request credentials. Set
28
+ * `varyByQuery` when the target preserves request query parameters so the SSR
29
+ * adapter can request a full-query cache key on providers that support it.
30
+ */
31
+ export declare function withSsrHtmlContentType<T extends Response>(response: T, options?: SsrHtmlContentTypeOptions): T;
10
32
  /**
11
33
  * Deployment-wide override for the SSR shell cache policy.
12
34
  *
@@ -7,6 +7,31 @@ export const DEFAULT_SSR_CACHE_HEADERS = {
7
7
  "cdn-cache-control": DEFAULT_SSR_CDN_CACHE_CONTROL,
8
8
  "netlify-cdn-cache-control": DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL,
9
9
  };
10
+ /**
11
+ * Content type used by impersonal HTML redirects that should enter the
12
+ * deployment adapter's shared SSR cache path.
13
+ */
14
+ export const SSR_HTML_CONTENT_TYPE = "text/html; charset=utf-8";
15
+ /**
16
+ * Internal response marker for public HTML whose redirect target preserves
17
+ * request query parameters. The SSR adapters consume this marker and emit a
18
+ * provider-specific full-query cache key only where the provider supports it.
19
+ */
20
+ export const SSR_QUERY_CACHE_KEY_HEADER = "x-agent-native-ssr-key";
21
+ /**
22
+ * Mark an already-built HTML response as HTML without changing its redirect
23
+ * status, location, or other headers. Only use this for redirects whose
24
+ * target is independent of the viewer and request credentials. Set
25
+ * `varyByQuery` when the target preserves request query parameters so the SSR
26
+ * adapter can request a full-query cache key on providers that support it.
27
+ */
28
+ export function withSsrHtmlContentType(response, options = {}) {
29
+ response.headers.set("content-type", SSR_HTML_CONTENT_TYPE);
30
+ if (options.varyByQuery) {
31
+ response.headers.set(SSR_QUERY_CACHE_KEY_HEADER, "query");
32
+ }
33
+ return response;
34
+ }
10
35
  /**
11
36
  * Deployment-wide override for the SSR shell cache policy.
12
37
  *
@@ -6,6 +6,7 @@ export { truncate } from "./truncate.js";
6
6
  export { isHumanReadableDocumentTitle, normalizeDocumentTitle, } from "./document-title.js";
7
7
  export { injectDocumentMarkup } from "./html-document.js";
8
8
  export { withBuilderUtmTrackingParams } from "./builder-link-tracking.js";
9
+ export { SSR_HTML_CONTENT_TYPE, SSR_QUERY_CACHE_KEY_HEADER, type SsrHtmlContentTypeOptions, withSsrHtmlContentType, } from "./cache-control.js";
9
10
  export { AGENT_NATIVE_DOCS_ORIGIN, docsUrl, type DocsUrlOptions, } from "./docs-url.js";
10
11
  export { buildRuntimeConfigPrompt, formatRuntimeConfigReport, getRuntimeConfigReport, parseRuntimeConfigReport, runtimeConfigRequirementsFromSearchParams, type RuntimeConfigEnvironment, type RuntimeConfigIssue, type RuntimeConfigIssueCode, type RuntimeConfigIssueSeverity, type RuntimeConfigPhase, type RuntimeConfigReport, type RuntimeConfigRequirements, } from "./runtime-config.js";
11
12
  export { llmConnectionTrackingProperties, normalizeLlmConnection, type LlmConnectionStatus, } from "./llm-connection.js";
@@ -6,6 +6,7 @@ export { truncate } from "./truncate.js";
6
6
  export { isHumanReadableDocumentTitle, normalizeDocumentTitle, } from "./document-title.js";
7
7
  export { injectDocumentMarkup } from "./html-document.js";
8
8
  export { withBuilderUtmTrackingParams } from "./builder-link-tracking.js";
9
+ export { SSR_HTML_CONTENT_TYPE, SSR_QUERY_CACHE_KEY_HEADER, withSsrHtmlContentType, } from "./cache-control.js";
9
10
  export { AGENT_NATIVE_DOCS_ORIGIN, docsUrl, } from "./docs-url.js";
10
11
  export { buildRuntimeConfigPrompt, formatRuntimeConfigReport, getRuntimeConfigReport, parseRuntimeConfigReport, runtimeConfigRequirementsFromSearchParams, } from "./runtime-config.js";
11
12
  export { llmConnectionTrackingProperties, normalizeLlmConnection, } from "./llm-connection.js";
@@ -11,7 +11,7 @@ description: "Mount the agent chat + resources into any React app with <AgentPan
11
11
 
12
12
  </Callout>
13
13
 
14
- You don't need to build agent-native from scratch. The agent chat, resources tab, CLI terminal, voice input, and all the related infrastructure ship as a handful of React components you drop into any app.
14
+ You don't need to build Agent-Native from scratch. The agent chat, resources tab, CLI terminal, voice input, and all the related infrastructure ship as a handful of React components you drop into any app.
15
15
 
16
16
  <Callout tone="info">
17
17
 
@@ -184,7 +184,7 @@ Full props: `AgentPanelProps` in `@agent-native/core/client`.
184
184
 
185
185
  ## Programmatic messages: `sendToAgentChat()` {#send}
186
186
 
187
- A button that hands work off to the agent (instead of running an inline `llm()` call — the anti-pattern from the [ladder](/docs/what-is-agent-native#the-ladder)). For visible, user-initiated AI work, open the sidebar explicitly so the user can see, steer, and continue the same thread:
187
+ A button that hands work off to the agent instead of creating a separate AI path with an inline `llm()` call. See [Why build apps this way](/docs/what-is-agent-native#why-build-apps-this-way) for why that distinction matters. For visible, user-initiated AI work, open the sidebar explicitly so the user can see, steer, and continue the same thread:
188
188
 
189
189
  ```tsx
190
190
  import { sendToAgentChat } from "@agent-native/core/client/agent-chat";
@@ -283,7 +283,7 @@ AI-shaped workflow inside one opaque action.
283
283
 
284
284
  ## Typesafe actions from the UI: `useActionMutation()` {#use-action-mutation}
285
285
 
286
- When the UI needs to run the same operation an agent tool would run — rung 3 of the [ladder](/docs/what-is-agent-native#rung-three) — use `useActionMutation`:
286
+ When the UI needs to run the same operation an agent tool would run, use [`useActionMutation`](/docs/client-data#use-action-mutation):
287
287
 
288
288
  ```tsx
289
289
  import { useActionMutation } from "@agent-native/core/client/hooks";
@@ -298,7 +298,7 @@ Type-safe arguments come from the zod schema in your `defineAction()`. See [Acti
298
298
 
299
299
  <Callout id="doc-block-1757zi5" tone="decision">
300
300
 
301
- **`useActionMutation` vs `sendToAgentChat`.** Run the operation directly with `useActionMutation` when the user clicked a deterministic button ("Send reply"). Hand it to `sendToAgentChat` when the work needs the agent's reasoning, tools, or multi-step planning. Never call an inline `llm()` from UI — that is rung 1 of the [ladder](/docs/what-is-agent-native#the-ladder).
301
+ **`useActionMutation` vs `sendToAgentChat`.** Run the operation directly with `useActionMutation` when the user clicked a deterministic button ("Send reply"). Hand it to `sendToAgentChat` when the work needs the agent's reasoning, tools, or multi-step planning. Never call an inline `llm()` from UI; that creates a separate AI path instead of using the shared agent loop.
302
302
 
303
303
  </Callout>
304
304
 
@@ -1,34 +1,34 @@
1
1
  ---
2
2
  title: "FAQ"
3
- description: "Common questions about agent-native — what it is, who it's for, what you can build, and how it works."
3
+ description: "Common questions about Agent-Native — what it is, who it's for, what you can build, and how it works."
4
4
  ---
5
5
 
6
6
  # FAQ
7
7
 
8
- Common questions about agent-native, organized from "I'm just looking" to "I'm wiring up auth right now."
8
+ Common questions about Agent-Native, organized from "I'm just looking" to "I'm wiring up auth right now."
9
9
 
10
10
  ## The basics {#general}
11
11
 
12
- ### What is agent-native? {#what-is-agent-native}
12
+ ### What is Agent-Native? {#what-is-agent-native}
13
13
 
14
- Agent-native is a framework for building apps where the AI agent and the product surface around it are equal partners. The usual path starts with chat, adds typed actions, renders structured results inline, and grows into durable pages around the same SQL state. The invariant is that agents and humans share the same actions, database, and state. See [What Is Agent-Native?](/docs/what-is-agent-native) for the full explanation.
14
+ Agent-Native is a framework for building apps where the AI agent and the product surface around it are equal partners. The usual path starts with chat, adds typed actions, renders structured results inline, and grows into durable pages around the same SQL state. The invariant is that agents and humans share the same actions, database, and state. See [What is Agent-Native?](/docs/what-is-agent-native) for the full explanation.
15
15
 
16
16
  ### Who is this for? {#who-is-this-for}
17
17
 
18
- Agent-native is for people who want a real app and an AI agent to work from the same data and actions. The common paths are:
18
+ Agent-Native is for people who want a real app and an AI agent to work from the same data and actions. The common paths are:
19
19
 
20
20
  - **Use a hosted app** if you want Mail, Calendar, Forms, Plan, or another finished template with no setup — start at the [template gallery](/templates).
21
21
  - **Start with Chat** if you want the default from-scratch path: users can talk to the agent immediately, then you extend with actions, native results, and screens — start with [Getting Started](/docs/getting-started) or [Chat](/docs/template-chat).
22
22
  - **Start automation-first** if you are building scheduled jobs, queues, scripts, integration workers, or external-agent workflows with no browser UI yet — start with [Automation-First Apps](/docs/pure-agent-apps).
23
23
  - **Start from a template and customize it** if you want your own SaaS product with auth, database, UI, and agent actions already wired — see [Templates](/docs/cloneable-saas).
24
24
  - **Build from scratch** if you want the framework primitives for a new agent-driven product — start with [Getting Started](/docs/getting-started).
25
- - **Connect another agent or code tool** if you want Claude, ChatGPT, Codex, Cursor, or GitHub Copilot / VS Code to use an agent-native app — see [External Agents](/docs/external-agents) and [Skills Guide](/docs/skills-guide).
25
+ - **Connect another agent or code tool** if you want Claude, ChatGPT, Codex, Cursor, or GitHub Copilot / VS Code to use an Agent-Native app — see [External Agents](/docs/external-agents) and [Skills Guide](/docs/skills-guide).
26
26
 
27
27
  ### How is this different from adding AI to an existing app? {#how-is-this-different}
28
28
 
29
- Most apps bolt AI on as an afterthought that can't actually _do_ things in the app. In an agent-native app the agent is a first-class citizen that shares the same actions, database, and state as the UI, so it can do anything the buttons can. See [What Is Agent-Native?](/docs/what-is-agent-native#the-ladder).
29
+ Most apps bolt AI on as an afterthought that can't actually _do_ things in the app. In an Agent-Native app the agent is a first-class citizen that shares the same actions, database, and state as the UI, so it can do anything the buttons can. See [Why build apps this way](/docs/what-is-agent-native#why-build-apps-this-way).
30
30
 
31
- <Diagram id="doc-block-1s6b04" title="Bolted-on AI vs. agent-native" summary="A bolted-on chat sidebar lives in its own world. An agent-native agent shares the same actions, database, and state as the UI.">
31
+ <Diagram id="doc-block-1s6b04" title="Bolted-on AI vs. Agent-Native" summary="A bolted-on chat sidebar lives in its own world. An Agent-Native agent shares the same actions, database, and state as the UI.">
32
32
 
33
33
  ```html
34
34
  <div class="diagram-vs">
@@ -45,7 +45,7 @@ Most apps bolt AI on as an afterthought that can't actually _do_ things in the a
45
45
  </div>
46
46
  <div class="diagram-divider" aria-hidden="true"></div>
47
47
  <div class="diagram-col">
48
- <span class="diagram-pill ok">Agent-native</span>
48
+ <span class="diagram-pill ok">Agent-Native</span>
49
49
  <div class="diagram-row2">
50
50
  <div class="diagram-node">UI</div>
51
51
  <div class="diagram-node">Agent</div>
@@ -114,9 +114,9 @@ Anthropic Claude, OpenAI (GPT-5 family), Google Gemini, and any provider that sp
114
114
 
115
115
  No. You don't train models, fine-tune, or deal with embeddings. You build a regular web app — and on the hosted version, you barely build anything at all. The framework handles the agent integration: routing messages, running actions, syncing state.
116
116
 
117
- ### Can I migrate an existing app to agent-native? {#can-i-use-existing-code}
117
+ ### Can I migrate an existing app to Agent-Native? {#can-i-use-existing-code}
118
118
 
119
- You can, but agent-native works best when built from the ground up. The architecture — shared database, polling sync, actions, application state — needs to be integrated throughout. Starting from an app and customizing it is the recommended path. Think of it like the shift from desktop-first to mobile-first: you _can_ retrofit, but building native is better.
119
+ You can, but Agent-Native works best when built from the ground up. The architecture — shared database, polling sync, actions, application state — needs to be integrated throughout. Starting from an app and customizing it is the recommended path. Think of it like the shift from desktop-first to mobile-first: you _can_ retrofit, but building native is better.
120
120
 
121
121
  ## Templates and what you can build {#templates}
122
122
 
@@ -148,7 +148,7 @@ Yes. The same agent runs in your web UI, in Slack, in Telegram, over email, and
148
148
 
149
149
  ### Can agents talk to each other? {#can-agents-talk-to-each-other}
150
150
 
151
- Yes, via the [A2A (Agent-to-Agent) protocol](/docs/a2a-protocol). Every agent-native app automatically gets an A2A endpoint. From the mail app, you can tag the analytics agent to query data. An agent discovers what other agents are available, calls them over the protocol, and shows results in the UI. No configuration needed — the agent card is auto-generated from your template's actions.
151
+ Yes, via the [A2A (Agent-to-Agent) protocol](/docs/a2a-protocol). Every Agent-Native app automatically gets an A2A endpoint. From the mail app, you can tag the analytics agent to query data. An agent discovers what other agents are available, calls them over the protocol, and shows results in the UI. No configuration needed — the agent card is auto-generated from your template's actions.
152
152
 
153
153
  ### What can the agent see in the app? {#what-can-the-agent-see}
154
154
 
@@ -156,7 +156,7 @@ The agent always knows what the user is currently viewing. The UI writes navigat
156
156
 
157
157
  ## Development questions {#development}
158
158
 
159
- ### Which AI coding tools work with agent-native? {#which-ai-tools-work}
159
+ ### Which AI coding tools work with Agent-Native? {#which-ai-tools-work}
160
160
 
161
161
  Any AI coding tool that reads project instructions. The framework uses AGENTS.md as the universal standard:
162
162
 
@@ -227,7 +227,7 @@ SSE gives same-process writes an immediate path to the browser, and a lightweigh
227
227
 
228
228
  AI is non-deterministic, so you need conversation flow to give feedback and iterate — not one-shot buttons — and the agent already has your codebase, instructions, skills, and history that an inline call lacks. Routing everything through the agent is also what lets the app be driven from Slack, Telegram, or another agent. See [Key Concepts — Agent chat bridge](/docs/key-concepts#agent-chat-bridge).
229
229
 
230
- ### How do I upgrade an older Agent Native app? {#upgrade-older-app}
230
+ ### How do I upgrade an older Agent-Native app? {#upgrade-older-app}
231
231
 
232
232
  Run the supported upgrade path from the app or workspace root:
233
233
 
@@ -251,7 +251,7 @@ The shared database, live sync, actions system, and application state only work
251
251
  ## What's next
252
252
 
253
253
  - [**Getting Started**](/docs/getting-started) — build your first action and render it inline in chat
254
- - [**What Is Agent-Native?**](/docs/what-is-agent-native) — the full explanation behind the answers above
254
+ - [**What is Agent-Native?**](/docs/what-is-agent-native) — the full explanation behind the answers above
255
255
  - [**Templates**](/docs/cloneable-saas) — start from a complete SaaS product instead of starting from scratch
256
256
  - [**Key Concepts**](/docs/key-concepts) — the architecture: SQL, actions, polling sync, and portability
257
257
  - [**Deployment**](/docs/deployment) — host on your own domain or any Nitro-compatible provider
@@ -1,69 +1,201 @@
1
1
  ---
2
2
  title: "Getting Started"
3
- description: "Create a Chat app and configure an agent, then extend it with an action and a page."
3
+ description: "Create an Agent-Native app and call the same action from the agent and the UI."
4
4
  ---
5
5
 
6
6
  # Getting Started
7
7
 
8
- Agent-Native apps give the agent and the UI the same [actions](/docs/actions-overview),
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.
8
+ Agent-Native is an open-source TypeScript framework for building apps that
9
+ serve both people and AI agents. You define your app's functionality once as
10
+ [actions](/docs/actions-overview)—typed functions that your React UI calls
11
+ from code and agents use as tools.
12
12
 
13
- <Steps>
13
+ In this guide, you'll create a Chat app and call its included `hello` action
14
+ from the agent and the UI.
14
15
 
15
- ### Create a chat app and configure an agent
16
+ ## Prerequisites
16
17
 
17
- Scaffold the Chat template, install dependencies, start the dev server, and
18
- configure an agent. You'll have a working chat app to extend.
19
- **You are here.**
18
+ - [Node.js](https://nodejs.org) 22 or later
19
+ - [pnpm](https://pnpm.io)
20
+ - An LLM connection for the agent: Builder.io, an Anthropic or OpenAI API key,
21
+ or a local Ollama model
20
22
 
21
- ### Add an action
23
+ ## Create an app
22
24
 
23
- Define a typed text analyzer and render its result as a chart in the chat.
25
+ In a new directory, create a Chat app:
24
26
 
25
- ### Add a page
26
-
27
- Build a React route that calls the same action outside the transcript.
28
-
29
- </Steps>
27
+ ```bash
28
+ npx @agent-native/core@latest create my-app --standalone --template chat
29
+ cd my-app
30
+ pnpm install
31
+ ```
30
32
 
31
- ## 1. Create a chat app {#create-your-app}
33
+ The template includes a browser app, authentication, durable conversations,
34
+ live sync, application context, and an `actions/` directory. It also includes a
35
+ small `hello` action that you'll use throughout this guide.
32
36
 
33
- You'll need [Node.js 22+](https://nodejs.org) and [pnpm](https://pnpm.io).
37
+ ## Start the development server
34
38
 
35
- Open a terminal, go to the directory where you want your Agent Native app, and run:
39
+ Start the app:
36
40
 
37
41
  ```bash
38
- npx @agent-native/core@latest create my-app --template chat
39
- cd my-app
40
- pnpm install
41
42
  pnpm dev
42
43
  ```
43
44
 
44
- The app opens at `http://localhost:8080`. If you see the login screen, sign up
45
- with a made-up login. Local development does not require email verification.
45
+ The app opens at `http://localhost:8080`. If it doesn't open automatically,
46
+ visit that URL in your browser.
47
+
48
+ <Callout tone="info">
49
+
50
+ On the Welcome screen, select **Continue as local dev**. You don't need to
51
+ enter an email or password for local development.
52
+
53
+ </Callout>
54
+
55
+ Next, connect an LLM. Select **Connect Builder.io** to use free credits, or
56
+ select **Custom keys**, choose a provider, and enter the requested connection
57
+ details.
58
+
59
+ ## Run the action from the agent
60
+
61
+ An action is a typed function that your React UI can call from code and agents
62
+ can use as a tool. The Chat template includes a simple `hello` action so you
63
+ can try the pattern before writing one yourself.
64
+
65
+ In the app, ask:
66
+
67
+ > Call the hello action for Alex.
68
+
69
+ The agent finds `hello` from its description and input schema, passes `Alex` as
70
+ the `name` input, and responds:
71
+
72
+ ```text
73
+ Hello, Alex!
74
+ ```
75
+
76
+ ## Inspect the action
77
+
78
+ Open `actions/hello.ts`:
79
+
80
+ ```ts filename="actions/hello.ts"
81
+ import { defineAction } from "@agent-native/core/action";
82
+ import { z } from "zod";
83
+
84
+ export default defineAction({
85
+ description: "Return a friendly greeting.",
86
+ schema: z.object({
87
+ name: z.string().default("world").describe("Name to greet"),
88
+ }),
89
+ http: { method: "GET" },
90
+ run: async ({ name }) => {
91
+ return { message: `Hello, ${name}!` };
92
+ },
93
+ });
94
+ ```
95
+
96
+ For now, focus on four parts:
97
+
98
+ - `description` tells the agent when to use the action.
99
+ - `schema` validates the input and gives the agent a typed tool definition.
100
+ - `http` exposes this read-only action through `GET`, which lets
101
+ `useActionQuery` call it from React.
102
+ - `run` contains the application logic shared by the agent and the UI.
103
+
104
+ Read [Defining Actions](/docs/actions-defining) for the complete API.
105
+
106
+ ## Call the action from React
107
+
108
+ Add a route at `app/routes/hello.tsx`:
109
+
110
+ ```tsx filename="app/routes/hello.tsx"
111
+ import { useActionQuery } from "@agent-native/core/client/hooks";
112
+ import { useState } from "react";
113
+
114
+ import { Input } from "@/components/ui/input";
115
+ import { Label } from "@/components/ui/label";
116
+
117
+ export default function HelloRoute() {
118
+ const [name, setName] = useState("Alex");
119
+ const { data } = useActionQuery("hello", { name });
120
+
121
+ return (
122
+ <main className="mx-auto grid w-full max-w-xl gap-6 p-6">
123
+ <h1 className="text-2xl font-semibold">Hello action</h1>
124
+ <div className="grid gap-2">
125
+ <Label htmlFor="name">Name</Label>
126
+ <Input
127
+ id="name"
128
+ value={name}
129
+ onChange={(event) => setName(event.target.value)}
130
+ />
131
+ </div>
132
+ <p className="text-xl font-medium">{data?.message}</p>
133
+ </main>
134
+ );
135
+ }
136
+ ```
137
+
138
+ <Callout tone="warning">
139
+
140
+ Restart the development server so it discovers the new route, then open
141
+ `http://localhost:8080/hello`.
142
+
143
+ </Callout>
144
+
145
+ As you type a name, `useActionQuery` calls `hello` and renders the result. It
146
+ infers the action's input and result types, so the page doesn't need a custom
147
+ API route or a second implementation of the greeting.
148
+
149
+ ## Change the action
150
+
151
+ In `actions/hello.ts`, change the return value:
152
+
153
+ ```ts
154
+ return { message: `Welcome, ${name}.` };
155
+ ```
156
+
157
+ Refresh `/hello`, then ask the agent to call `hello` again. Both return the
158
+ updated greeting because they call the same action.
159
+
160
+ ## Call actions in other ways
161
+
162
+ You called the same action from the agent and UI. The same action can also be
163
+ called from:
164
+
165
+ | Call from | Use it to |
166
+ | --------------------------------------- | ------------------------------------------------------------- |
167
+ | [HTTP API](/docs/http-api) | Call an action from a script, backend, or integration. |
168
+ | [CLI](/docs/actions-other-surfaces#cli) | Run or test an action from a terminal. |
169
+ | [MCP](/docs/actions-other-surfaces#mcp) | Let an external AI client discover and call actions as tools. |
170
+ | [A2A](/docs/actions-other-surfaces#a2a) | Let another Agent-Native app ask this app to do work. |
171
+
172
+ Every caller uses the same action definition. You do not need a separate
173
+ implementation for each one. This shared action model is central to
174
+ Agent-Native: behavior, validation, and permissions stay aligned across the
175
+ UI, agents, and integrations as the app changes.
176
+
177
+ ## What you built
178
+
179
+ You created an Agent-Native app, called its `hello` action from the agent and a
180
+ React UI, then changed the greeting once and watched both update. Every action
181
+ you write from here follows that same pattern.
182
+
183
+ ## Next steps
46
184
 
47
- The Chat template includes durable chat threads, auth, live sync, an
48
- `actions/` directory, and the standard `view-screen` and `navigate` actions.
185
+ <Cards>
49
186
 
50
- ### Choose a different starting point
187
+ ### [What is Agent-Native?](/docs/what-is-agent-native)
51
188
 
52
- If Chat is not the right starting point, run `create` without `--template` and
53
- choose another option in the CLI. See [Creating Templates](/docs/creating-templates)
54
- for the other paths.
189
+ Understand why the UI and agent share actions, data, and context.
55
190
 
56
- ## 2. Configure an agent {#connect-ai}
191
+ ### [Key Concepts](/docs/key-concepts)
57
192
 
58
- The Chat template opens directly to the chat surface. If the agent is not ready
59
- to respond, open **Settings > Manage agent** or use **Cmd/Ctrl+K > Manage agent**
60
- to configure a model and provider.
193
+ Learn how actions, SQL data, application context, access, and live sync fit
194
+ together.
61
195
 
62
- Once the agent responds, continue with [Add an Action](/docs/getting-started-actions).
196
+ ### [Actions](/docs/actions-overview)
63
197
 
64
- ## Related docs
198
+ Define actions for reads, writes, and approvals, then call them from the UI,
199
+ agents, and external clients.
65
200
 
66
- - [What Is Agent-Native?](/docs/what-is-agent-native): the architecture behind this path.
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.
69
- - [FAQ](/docs/faq): answers about models, hosting, and templates.
201
+ </Cards>