@agent-native/core 0.59.1 → 0.60.0

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 (188) hide show
  1. package/dist/a2a/index.d.ts +2 -0
  2. package/dist/a2a/index.d.ts.map +1 -1
  3. package/dist/a2a/index.js +1 -0
  4. package/dist/a2a/index.js.map +1 -1
  5. package/dist/a2a/invoke.d.ts +63 -0
  6. package/dist/a2a/invoke.d.ts.map +1 -0
  7. package/dist/a2a/invoke.js +157 -0
  8. package/dist/a2a/invoke.js.map +1 -0
  9. package/dist/agent/run-store.d.ts +15 -0
  10. package/dist/agent/run-store.d.ts.map +1 -1
  11. package/dist/agent/run-store.js +28 -0
  12. package/dist/agent/run-store.js.map +1 -1
  13. package/dist/chat-threads/store.d.ts +21 -0
  14. package/dist/chat-threads/store.d.ts.map +1 -1
  15. package/dist/chat-threads/store.js +128 -0
  16. package/dist/chat-threads/store.js.map +1 -1
  17. package/dist/cli/agent.d.ts +23 -0
  18. package/dist/cli/agent.d.ts.map +1 -0
  19. package/dist/cli/agent.js +300 -0
  20. package/dist/cli/agent.js.map +1 -0
  21. package/dist/cli/agents.d.ts +14 -0
  22. package/dist/cli/agents.d.ts.map +1 -0
  23. package/dist/cli/agents.js +95 -0
  24. package/dist/cli/agents.js.map +1 -0
  25. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  26. package/dist/cli/code-agent-executor.js +264 -2
  27. package/dist/cli/code-agent-executor.js.map +1 -1
  28. package/dist/cli/create.d.ts +3 -2
  29. package/dist/cli/create.d.ts.map +1 -1
  30. package/dist/cli/create.js +154 -83
  31. package/dist/cli/create.js.map +1 -1
  32. package/dist/cli/index.js +50 -2
  33. package/dist/cli/index.js.map +1 -1
  34. package/dist/cli/invoke.d.ts +26 -0
  35. package/dist/cli/invoke.d.ts.map +1 -0
  36. package/dist/cli/invoke.js +227 -0
  37. package/dist/cli/invoke.js.map +1 -0
  38. package/dist/cli/templates-meta.d.ts +1 -1
  39. package/dist/cli/templates-meta.d.ts.map +1 -1
  40. package/dist/cli/templates-meta.js +9 -8
  41. package/dist/cli/templates-meta.js.map +1 -1
  42. package/dist/cli/workspacify.d.ts +1 -1
  43. package/dist/cli/workspacify.d.ts.map +1 -1
  44. package/dist/cli/workspacify.js +6 -6
  45. package/dist/cli/workspacify.js.map +1 -1
  46. package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
  47. package/dist/client/NewWorkspaceAppFlow.js +5 -4
  48. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  49. package/dist/client/blocks/library/diagram.d.ts.map +1 -1
  50. package/dist/client/blocks/library/diagram.js +23 -17
  51. package/dist/client/blocks/library/diagram.js.map +1 -1
  52. package/dist/client/blocks/types.d.ts +2 -0
  53. package/dist/client/blocks/types.d.ts.map +1 -1
  54. package/dist/client/blocks/types.js.map +1 -1
  55. package/dist/client/chat/index.d.ts +1 -1
  56. package/dist/client/chat/index.d.ts.map +1 -1
  57. package/dist/client/chat/index.js.map +1 -1
  58. package/dist/client/index.d.ts +1 -1
  59. package/dist/client/index.d.ts.map +1 -1
  60. package/dist/client/index.js.map +1 -1
  61. package/dist/client/use-chat-threads.d.ts +13 -0
  62. package/dist/client/use-chat-threads.d.ts.map +1 -1
  63. package/dist/client/use-chat-threads.js +41 -0
  64. package/dist/client/use-chat-threads.js.map +1 -1
  65. package/dist/integrations/plugin.d.ts.map +1 -1
  66. package/dist/integrations/plugin.js +2 -2
  67. package/dist/integrations/plugin.js.map +1 -1
  68. package/dist/onboarding/default-steps.d.ts.map +1 -1
  69. package/dist/onboarding/default-steps.js +102 -0
  70. package/dist/onboarding/default-steps.js.map +1 -1
  71. package/dist/provider-api/actions/github-repo-files.d.ts +84 -0
  72. package/dist/provider-api/actions/github-repo-files.d.ts.map +1 -0
  73. package/dist/provider-api/actions/github-repo-files.js +213 -0
  74. package/dist/provider-api/actions/github-repo-files.js.map +1 -0
  75. package/dist/provider-api/github-repo.d.ts +11 -0
  76. package/dist/provider-api/github-repo.d.ts.map +1 -0
  77. package/dist/provider-api/github-repo.js +553 -0
  78. package/dist/provider-api/github-repo.js.map +1 -0
  79. package/dist/provider-api/index.d.ts +184 -11
  80. package/dist/provider-api/index.d.ts.map +1 -1
  81. package/dist/provider-api/index.js +519 -0
  82. package/dist/provider-api/index.js.map +1 -1
  83. package/dist/scripts/docs/search.d.ts.map +1 -1
  84. package/dist/scripts/docs/search.js +38 -13
  85. package/dist/scripts/docs/search.js.map +1 -1
  86. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  87. package/dist/secrets/register-framework-secrets.js +11 -0
  88. package/dist/secrets/register-framework-secrets.js.map +1 -1
  89. package/dist/server/agent-chat-plugin.d.ts +32 -0
  90. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  91. package/dist/server/agent-chat-plugin.js +297 -2
  92. package/dist/server/agent-chat-plugin.js.map +1 -1
  93. package/dist/server/auth-marketing.d.ts.map +1 -1
  94. package/dist/server/auth-marketing.js +17 -7
  95. package/dist/server/auth-marketing.js.map +1 -1
  96. package/dist/server/auth.d.ts.map +1 -1
  97. package/dist/server/auth.js +6 -0
  98. package/dist/server/auth.js.map +1 -1
  99. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  100. package/dist/server/core-routes-plugin.js +18 -98
  101. package/dist/server/core-routes-plugin.js.map +1 -1
  102. package/dist/styles/blocks.css +30 -8
  103. package/dist/styles/rich-markdown-editor.css +10 -4
  104. package/dist/templates/{starter-shell-sync.spec.ts → chat-shell-sync.spec.ts} +21 -21
  105. package/dist/templates/default/.agents/skills/actions/SKILL.md +5 -5
  106. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +63 -0
  107. package/dist/templates/default/AGENTS.md +22 -1
  108. package/dist/templates/default/actions/hello.ts +1 -1
  109. package/dist/templates/default/actions/navigate.ts +1 -1
  110. package/dist/templates/default/actions/view-screen.ts +1 -1
  111. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +63 -0
  112. package/dist/templates/headless/.env.example +4 -0
  113. package/dist/templates/headless/.prettierrc +5 -0
  114. package/dist/templates/headless/AGENTS.md +58 -0
  115. package/dist/templates/headless/DEVELOPING.md +22 -0
  116. package/dist/templates/headless/_gitignore +36 -0
  117. package/dist/templates/headless/actions/hello.ts +14 -0
  118. package/dist/templates/headless/actions/run.ts +3 -0
  119. package/dist/templates/headless/package.json +22 -0
  120. package/dist/templates/headless/tsconfig.json +7 -0
  121. package/dist/templates/ui-primitives-sync.spec.ts +2 -2
  122. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -5
  123. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +63 -0
  124. package/dist/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +93 -0
  125. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +1 -1
  126. package/dist/templates/workspace-core/AGENTS.md +20 -3
  127. package/dist/templates/workspace-core/src/server/index.ts +1 -1
  128. package/dist/templates/workspace-root/AGENTS.md +25 -5
  129. package/dist/templates/workspace-root/README.md +7 -7
  130. package/dist/triggers/dispatcher.d.ts +2 -3
  131. package/dist/triggers/dispatcher.d.ts.map +1 -1
  132. package/dist/triggers/dispatcher.js +2 -3
  133. package/dist/triggers/dispatcher.js.map +1 -1
  134. package/dist/triggers/routes.d.ts +38 -0
  135. package/dist/triggers/routes.d.ts.map +1 -0
  136. package/dist/triggers/routes.js +202 -0
  137. package/dist/triggers/routes.js.map +1 -0
  138. package/docs/AGENTS.md +57 -0
  139. package/docs/SKILL.md +40 -0
  140. package/docs/content/a2a-protocol.md +1 -1
  141. package/docs/content/actions.md +48 -8
  142. package/docs/content/agent-surfaces.md +76 -14
  143. package/docs/content/cli-adapters.md +1 -1
  144. package/docs/content/cloneable-saas.md +5 -4
  145. package/docs/content/code-agents-ui.md +1 -1
  146. package/docs/content/components.md +1 -1
  147. package/docs/content/context-awareness.md +1 -1
  148. package/docs/content/creating-templates.md +9 -7
  149. package/docs/content/drop-in-agent.md +1 -1
  150. package/docs/content/faq.md +6 -4
  151. package/docs/content/getting-started.md +63 -73
  152. package/docs/content/key-concepts.md +24 -24
  153. package/docs/content/native-chat-ui.md +4 -4
  154. package/docs/content/pure-agent-apps.md +34 -10
  155. package/docs/content/security.md +1 -1
  156. package/docs/content/server.md +1 -1
  157. package/docs/content/template-chat.md +85 -0
  158. package/docs/content/template-dispatch.md +1 -1
  159. package/docs/content/tracking.md +1 -1
  160. package/docs/content/what-is-agent-native.md +7 -6
  161. package/package.json +10 -1
  162. package/src/templates/{starter-shell-sync.spec.ts → chat-shell-sync.spec.ts} +21 -21
  163. package/src/templates/default/.agents/skills/actions/SKILL.md +5 -5
  164. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +63 -0
  165. package/src/templates/default/AGENTS.md +22 -1
  166. package/src/templates/default/actions/hello.ts +1 -1
  167. package/src/templates/default/actions/navigate.ts +1 -1
  168. package/src/templates/default/actions/view-screen.ts +1 -1
  169. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +63 -0
  170. package/src/templates/headless/.env.example +4 -0
  171. package/src/templates/headless/.prettierrc +5 -0
  172. package/src/templates/headless/AGENTS.md +58 -0
  173. package/src/templates/headless/DEVELOPING.md +22 -0
  174. package/src/templates/headless/_gitignore +36 -0
  175. package/src/templates/headless/actions/hello.ts +14 -0
  176. package/src/templates/headless/actions/run.ts +3 -0
  177. package/src/templates/headless/package.json +22 -0
  178. package/src/templates/headless/tsconfig.json +7 -0
  179. package/src/templates/ui-primitives-sync.spec.ts +2 -2
  180. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -5
  181. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +63 -0
  182. package/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +93 -0
  183. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +1 -1
  184. package/src/templates/workspace-core/AGENTS.md +20 -3
  185. package/src/templates/workspace-core/src/server/index.ts +1 -1
  186. package/src/templates/workspace-root/AGENTS.md +25 -5
  187. package/src/templates/workspace-root/README.md +7 -7
  188. package/docs/content/template-starter.md +0 -78
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/triggers/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;AAkBZ,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,yBAAyB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AA2HD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAahC;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,CAkD9B;AAWD,wBAAgB,wBAAwB;;;;IA8DvC"}
@@ -0,0 +1,202 @@
1
+ import { defineEventHandler, getMethod, setResponseStatus, } from "h3";
2
+ import { readBody } from "../server/h3-helpers.js";
3
+ import { getSession } from "../server/auth.js";
4
+ import { getDbExec } from "../db/client.js";
5
+ import { nextOccurrence, describeCron, isValidCron } from "../jobs/cron.js";
6
+ import { getOrgContext } from "../org/context.js";
7
+ import { resourceGetByPath, resourceListAllOwners, resourcePut, SHARED_OWNER, } from "../resources/store.js";
8
+ import { buildTriggerContent, parseTriggerFrontmatter, refreshEventSubscriptions, } from "./dispatcher.js";
9
+ function automationName(path) {
10
+ return path.replace(/^jobs\//, "").replace(/\.md$/, "");
11
+ }
12
+ function normalizeAutomationPath(input) {
13
+ const rawPath = input.path ?? (input.name ? `jobs/${input.name}.md` : "");
14
+ const path = rawPath.replace(/^\/+/, "");
15
+ if (!path.startsWith("jobs/") ||
16
+ !path.endsWith(".md") ||
17
+ path.endsWith(".keep") ||
18
+ path.includes("..")) {
19
+ throw Object.assign(new Error("A valid jobs/*.md automation path is required"), {
20
+ statusCode: 400,
21
+ });
22
+ }
23
+ return path;
24
+ }
25
+ function scheduleDescription(schedule) {
26
+ if (!schedule)
27
+ return undefined;
28
+ try {
29
+ return describeCron(schedule);
30
+ }
31
+ catch {
32
+ return schedule;
33
+ }
34
+ }
35
+ function nextRunForMeta(meta) {
36
+ if (meta.nextRun)
37
+ return meta.nextRun;
38
+ if (meta.enabled &&
39
+ meta.triggerType !== "event" &&
40
+ meta.schedule &&
41
+ isValidCron(meta.schedule)) {
42
+ try {
43
+ return nextOccurrence(meta.schedule).toISOString();
44
+ }
45
+ catch {
46
+ return undefined;
47
+ }
48
+ }
49
+ return undefined;
50
+ }
51
+ async function currentUserCanUpdateAutomation(event, userEmail, resourceOwner, meta) {
52
+ if (resourceOwner === userEmail)
53
+ return true;
54
+ if (resourceOwner !== SHARED_OWNER)
55
+ return false;
56
+ if (meta.createdBy &&
57
+ meta.createdBy.toLowerCase() === userEmail.toLowerCase()) {
58
+ return true;
59
+ }
60
+ let orgId = meta.orgId;
61
+ if (!orgId) {
62
+ try {
63
+ orgId = (await getOrgContext(event)).orgId ?? undefined;
64
+ }
65
+ catch {
66
+ orgId = undefined;
67
+ }
68
+ }
69
+ if (!orgId)
70
+ return false;
71
+ try {
72
+ const { rows } = await getDbExec().execute({
73
+ sql: `SELECT role FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,
74
+ args: [orgId, userEmail.toLowerCase()],
75
+ });
76
+ const role = String(rows[0]?.role ?? "").toLowerCase();
77
+ return role === "owner" || role === "admin";
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ async function resourceToAutomationItem(event, userEmail, resource) {
84
+ const { meta, body } = parseTriggerFrontmatter(resource.content);
85
+ return {
86
+ id: resource.id,
87
+ name: automationName(resource.path),
88
+ path: resource.path,
89
+ owner: resource.owner,
90
+ canUpdate: await currentUserCanUpdateAutomation(event, userEmail, resource.owner, meta),
91
+ triggerType: meta.triggerType,
92
+ event: meta.event,
93
+ schedule: meta.schedule || undefined,
94
+ scheduleDescription: scheduleDescription(meta.schedule),
95
+ condition: meta.condition,
96
+ mode: meta.mode,
97
+ domain: meta.domain,
98
+ enabled: meta.enabled,
99
+ lastStatus: meta.lastStatus,
100
+ lastRun: meta.lastRun,
101
+ lastError: meta.lastError,
102
+ nextRun: nextRunForMeta(meta),
103
+ createdBy: meta.createdBy,
104
+ body,
105
+ };
106
+ }
107
+ export async function listAutomationsForOwner(event, userEmail) {
108
+ const allResources = await resourceListAllOwners("jobs/");
109
+ const resources = allResources.filter((resource) => (resource.owner === userEmail || resource.owner === SHARED_OWNER) &&
110
+ resource.path.endsWith(".md") &&
111
+ !resource.path.endsWith(".keep"));
112
+ return Promise.all(resources.map((resource) => resourceToAutomationItem(event, userEmail, resource)));
113
+ }
114
+ export async function setAutomationEnabledForOwner(event, userEmail, input) {
115
+ if (typeof input.enabled !== "boolean") {
116
+ throw Object.assign(new Error("enabled must be a boolean"), {
117
+ statusCode: 400,
118
+ });
119
+ }
120
+ const path = normalizeAutomationPath(input);
121
+ const requestedOwner = input.owner === SHARED_OWNER ? SHARED_OWNER : userEmail;
122
+ const resource = await resourceGetByPath(requestedOwner, path);
123
+ if (!resource) {
124
+ throw Object.assign(new Error("Automation not found"), { statusCode: 404 });
125
+ }
126
+ const { meta, body } = parseTriggerFrontmatter(resource.content);
127
+ const allowed = await currentUserCanUpdateAutomation(event, userEmail, resource.owner, meta);
128
+ if (!allowed) {
129
+ throw Object.assign(new Error("Only the automation creator or an org admin can update it."), { statusCode: 403 });
130
+ }
131
+ meta.enabled = input.enabled;
132
+ if (meta.enabled &&
133
+ meta.triggerType !== "event" &&
134
+ meta.schedule &&
135
+ isValidCron(meta.schedule)) {
136
+ meta.nextRun = nextOccurrence(meta.schedule).toISOString();
137
+ }
138
+ await resourcePut(resource.owner, resource.path, buildTriggerContent(meta, body));
139
+ await refreshEventSubscriptions();
140
+ return resourceToAutomationItem(event, userEmail, {
141
+ ...resource,
142
+ content: buildTriggerContent(meta, body),
143
+ });
144
+ }
145
+ function routeError(event, err, fallback) {
146
+ const statusCode = typeof err?.statusCode === "number"
147
+ ? err.statusCode
148
+ : 500;
149
+ setResponseStatus(event, statusCode);
150
+ return { error: err?.message ?? fallback };
151
+ }
152
+ export function createAutomationsHandler() {
153
+ return defineEventHandler(async (event) => {
154
+ const method = getMethod(event);
155
+ const pathname = (event.path || event.url?.pathname || "")
156
+ .split("?")[0]
157
+ .replace(/^\/+/, "")
158
+ .replace(/\/+$/, "");
159
+ const session = await getSession(event).catch(() => null);
160
+ if (!session?.email) {
161
+ setResponseStatus(event, 401);
162
+ return { error: "Unauthenticated" };
163
+ }
164
+ if ((pathname === "fire-test" || pathname.endsWith("/fire-test")) &&
165
+ method === "POST") {
166
+ try {
167
+ const { emit } = await import("../event-bus/index.js");
168
+ const body = (await readBody(event).catch(() => ({})));
169
+ emit("test.event.fired", { data: body.data ?? {} }, { owner: session.email });
170
+ return { ok: true };
171
+ }
172
+ catch (err) {
173
+ return routeError(event, err, "Failed to emit test event");
174
+ }
175
+ }
176
+ if (method === "GET") {
177
+ try {
178
+ return await listAutomationsForOwner(event, session.email);
179
+ }
180
+ catch (err) {
181
+ return routeError(event, err, "Failed to list automations");
182
+ }
183
+ }
184
+ if (method === "PATCH" || method === "PUT") {
185
+ try {
186
+ const body = (await readBody(event).catch(() => ({})));
187
+ return await setAutomationEnabledForOwner(event, session.email, {
188
+ owner: body?.owner,
189
+ path: body?.path,
190
+ name: body?.name,
191
+ enabled: body?.enabled,
192
+ });
193
+ }
194
+ catch (err) {
195
+ return routeError(event, err, "Failed to update automation");
196
+ }
197
+ }
198
+ setResponseStatus(event, 405);
199
+ return { error: "Method not allowed" };
200
+ });
201
+ }
202
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/triggers/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport { getSession } from \"../server/auth.js\";\nimport { getDbExec } from \"../db/client.js\";\nimport { nextOccurrence, describeCron, isValidCron } from \"../jobs/cron.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport {\n resourceGetByPath,\n resourceListAllOwners,\n resourcePut,\n SHARED_OWNER,\n type Resource,\n} from \"../resources/store.js\";\nimport {\n buildTriggerContent,\n parseTriggerFrontmatter,\n refreshEventSubscriptions,\n} from \"./dispatcher.js\";\nimport type { TriggerFrontmatter } from \"./types.js\";\n\nexport interface AutomationRouteItem {\n id: string;\n name: string;\n path: string;\n owner: string;\n canUpdate: boolean;\n triggerType: TriggerFrontmatter[\"triggerType\"];\n event?: string;\n schedule?: string;\n scheduleDescription?: string;\n condition?: string;\n mode: TriggerFrontmatter[\"mode\"];\n domain?: string;\n enabled: boolean;\n lastStatus?: TriggerFrontmatter[\"lastStatus\"];\n lastRun?: string;\n lastError?: string;\n nextRun?: string;\n createdBy?: string;\n body: string;\n}\n\ninterface SetAutomationEnabledInput {\n owner?: string;\n path?: string;\n name?: string;\n enabled: boolean;\n}\n\nfunction automationName(path: string): string {\n return path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n}\n\nfunction normalizeAutomationPath(input: SetAutomationEnabledInput): string {\n const rawPath = input.path ?? (input.name ? `jobs/${input.name}.md` : \"\");\n const path = rawPath.replace(/^\\/+/, \"\");\n if (\n !path.startsWith(\"jobs/\") ||\n !path.endsWith(\".md\") ||\n path.endsWith(\".keep\") ||\n path.includes(\"..\")\n ) {\n throw Object.assign(\n new Error(\"A valid jobs/*.md automation path is required\"),\n {\n statusCode: 400,\n },\n );\n }\n return path;\n}\n\nfunction scheduleDescription(schedule: string | undefined): string | undefined {\n if (!schedule) return undefined;\n try {\n return describeCron(schedule);\n } catch {\n return schedule;\n }\n}\n\nfunction nextRunForMeta(meta: TriggerFrontmatter): string | undefined {\n if (meta.nextRun) return meta.nextRun;\n if (\n meta.enabled &&\n meta.triggerType !== \"event\" &&\n meta.schedule &&\n isValidCron(meta.schedule)\n ) {\n try {\n return nextOccurrence(meta.schedule).toISOString();\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\nasync function currentUserCanUpdateAutomation(\n event: H3Event,\n userEmail: string,\n resourceOwner: string,\n meta: TriggerFrontmatter,\n): Promise<boolean> {\n if (resourceOwner === userEmail) return true;\n if (resourceOwner !== SHARED_OWNER) return false;\n\n if (\n meta.createdBy &&\n meta.createdBy.toLowerCase() === userEmail.toLowerCase()\n ) {\n return true;\n }\n\n let orgId = meta.orgId;\n if (!orgId) {\n try {\n orgId = (await getOrgContext(event)).orgId ?? undefined;\n } catch {\n orgId = undefined;\n }\n }\n if (!orgId) return false;\n\n try {\n const { rows } = await getDbExec().execute({\n sql: `SELECT role FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,\n args: [orgId, userEmail.toLowerCase()],\n });\n const role = String((rows[0] as any)?.role ?? \"\").toLowerCase();\n return role === \"owner\" || role === \"admin\";\n } catch {\n return false;\n }\n}\n\nasync function resourceToAutomationItem(\n event: H3Event,\n userEmail: string,\n resource: Resource,\n): Promise<AutomationRouteItem> {\n const { meta, body } = parseTriggerFrontmatter(resource.content);\n return {\n id: resource.id,\n name: automationName(resource.path),\n path: resource.path,\n owner: resource.owner,\n canUpdate: await currentUserCanUpdateAutomation(\n event,\n userEmail,\n resource.owner,\n meta,\n ),\n triggerType: meta.triggerType,\n event: meta.event,\n schedule: meta.schedule || undefined,\n scheduleDescription: scheduleDescription(meta.schedule),\n condition: meta.condition,\n mode: meta.mode,\n domain: meta.domain,\n enabled: meta.enabled,\n lastStatus: meta.lastStatus,\n lastRun: meta.lastRun,\n lastError: meta.lastError,\n nextRun: nextRunForMeta(meta),\n createdBy: meta.createdBy,\n body,\n };\n}\n\nexport async function listAutomationsForOwner(\n event: H3Event,\n userEmail: string,\n): Promise<AutomationRouteItem[]> {\n const allResources = await resourceListAllOwners(\"jobs/\");\n const resources = allResources.filter(\n (resource) =>\n (resource.owner === userEmail || resource.owner === SHARED_OWNER) &&\n resource.path.endsWith(\".md\") &&\n !resource.path.endsWith(\".keep\"),\n );\n return Promise.all(\n resources.map((resource) =>\n resourceToAutomationItem(event, userEmail, resource),\n ),\n );\n}\n\nexport async function setAutomationEnabledForOwner(\n event: H3Event,\n userEmail: string,\n input: SetAutomationEnabledInput,\n): Promise<AutomationRouteItem> {\n if (typeof input.enabled !== \"boolean\") {\n throw Object.assign(new Error(\"enabled must be a boolean\"), {\n statusCode: 400,\n });\n }\n\n const path = normalizeAutomationPath(input);\n const requestedOwner =\n input.owner === SHARED_OWNER ? SHARED_OWNER : userEmail;\n const resource = await resourceGetByPath(requestedOwner, path);\n if (!resource) {\n throw Object.assign(new Error(\"Automation not found\"), { statusCode: 404 });\n }\n\n const { meta, body } = parseTriggerFrontmatter(resource.content);\n const allowed = await currentUserCanUpdateAutomation(\n event,\n userEmail,\n resource.owner,\n meta,\n );\n if (!allowed) {\n throw Object.assign(\n new Error(\"Only the automation creator or an org admin can update it.\"),\n { statusCode: 403 },\n );\n }\n\n meta.enabled = input.enabled;\n if (\n meta.enabled &&\n meta.triggerType !== \"event\" &&\n meta.schedule &&\n isValidCron(meta.schedule)\n ) {\n meta.nextRun = nextOccurrence(meta.schedule).toISOString();\n }\n\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n await refreshEventSubscriptions();\n\n return resourceToAutomationItem(event, userEmail, {\n ...resource,\n content: buildTriggerContent(meta, body),\n });\n}\n\nfunction routeError(event: H3Event, err: unknown, fallback: string) {\n const statusCode =\n typeof (err as any)?.statusCode === \"number\"\n ? (err as any).statusCode\n : 500;\n setResponseStatus(event, statusCode);\n return { error: (err as any)?.message ?? fallback };\n}\n\nexport function createAutomationsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.path || event.url?.pathname || \"\")\n .split(\"?\")[0]\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Unauthenticated\" };\n }\n\n if (\n (pathname === \"fire-test\" || pathname.endsWith(\"/fire-test\")) &&\n method === \"POST\"\n ) {\n try {\n const { emit } = await import(\"../event-bus/index.js\");\n const body = (await readBody(event).catch(() => ({}))) as Record<\n string,\n unknown\n >;\n emit(\n \"test.event.fired\",\n { data: body.data ?? {} },\n { owner: session.email },\n );\n return { ok: true };\n } catch (err) {\n return routeError(event, err, \"Failed to emit test event\");\n }\n }\n\n if (method === \"GET\") {\n try {\n return await listAutomationsForOwner(event, session.email);\n } catch (err) {\n return routeError(event, err, \"Failed to list automations\");\n }\n }\n\n if (method === \"PATCH\" || method === \"PUT\") {\n try {\n const body = (await readBody(event).catch(\n () => ({}),\n )) as SetAutomationEnabledInput | null;\n return await setAutomationEnabledForOwner(event, session.email, {\n owner: body?.owner,\n path: body?.path,\n name: body?.name,\n enabled: (body as any)?.enabled,\n } as SetAutomationEnabledInput);\n } catch (err) {\n return routeError(event, err, \"Failed to update automation\");\n }\n }\n\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n });\n}\n"]}
package/docs/AGENTS.md ADDED
@@ -0,0 +1,57 @@
1
+ # Agent Native Docs For Agents
2
+
3
+ These docs are bundled with `@agent-native/core` and installed at:
4
+
5
+ ```txt
6
+ node_modules/@agent-native/core/docs
7
+ ```
8
+
9
+ Use these version-matched markdown docs before coding against Agent Native
10
+ framework APIs or advanced features. Public docs are useful for browsing, but
11
+ the package docs match the exact framework version installed in the app.
12
+
13
+ ## Fast Lookup
14
+
15
+ From a generated app root:
16
+
17
+ ```bash
18
+ pnpm action docs-search --list
19
+ pnpm action docs-search --query "actions"
20
+ pnpm action docs-search --slug actions
21
+ ```
22
+
23
+ The built-in app agent also has a read-only `docs-search` tool with the same
24
+ `list`, `query`, and `slug` options.
25
+
26
+ If the action runner is unavailable, search the markdown files directly:
27
+
28
+ ```bash
29
+ rg -n "actions|automations|a2a|sharing" node_modules/@agent-native/core/docs
30
+ ```
31
+
32
+ Then read the matching files under `node_modules/@agent-native/core/docs/content/`.
33
+
34
+ ## What To Read First
35
+
36
+ | Task | Start with |
37
+ | ------------------------------------- | -------------------------------------------------------------------------------------------------------- |
38
+ | Define or call app operations | `content/actions.md`, `content/client.md` |
39
+ | Add SQL data, schema, or access rules | `content/database.md`, `content/security.md`, `content/sharing.md` |
40
+ | Keep the UI and agent in sync | `content/context-awareness.md`, `content/client.md` |
41
+ | Build headless or chat-first apps | `content/pure-agent-apps.md`, `content/agent-surfaces.md`, `content/using-your-agent.md` |
42
+ | Add automations or scheduled work | `content/automations.md`, `content/recurring-jobs.md` |
43
+ | Compose apps or call sibling agents | `content/a2a-protocol.md`, `content/multi-app-workspace.md`, `content/workspace.md` |
44
+ | Expose tools to external agents | `content/external-agents.md`, `content/mcp-protocol.md`, `content/mcp-apps.md`, `content/mcp-clients.md` |
45
+ | Add integrations, setup, or secrets | `content/onboarding.md`, `content/workspace-connections.md`, `content/security.md` |
46
+ | Build extensions or custom widgets | `content/extensions.md`, `content/agent-web-surfaces.md` |
47
+ | Deploy or configure hosting | `content/deployment.md`, `content/server.md` |
48
+ | Write agent instructions or skills | `content/skills-guide.md`, `content/writing-agent-instructions.md` |
49
+
50
+ ## Rules
51
+
52
+ - Prefer the app's own `AGENTS.md` and `.agents/skills/` for app-specific
53
+ behavior. Use this package docs tree for framework APIs and patterns.
54
+ - If local instructions and package docs conflict, local app instructions win
55
+ for that app, but verify the framework API shape in package docs or types.
56
+ - Do not invent Agent Native APIs. Search these docs and installed type
57
+ definitions before adding imports, routes, actions, or framework config.
package/docs/SKILL.md ADDED
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: agent-native-docs
3
+ description: "How to look up version-matched Agent Native framework docs in node_modules. Use before coding against @agent-native/core APIs or advanced features."
4
+ ---
5
+
6
+ # Agent Native Docs Lookup
7
+
8
+ ## Rule
9
+
10
+ Before implementing non-trivial Agent Native functionality, read the
11
+ version-matched docs installed with `@agent-native/core`.
12
+
13
+ ## How
14
+
15
+ 1. Start from the generated app root.
16
+ 2. Search with `pnpm action docs-search --query "<feature>"`.
17
+ 3. Read a specific page with `pnpm action docs-search --slug <slug>`.
18
+ 4. If the action runner is unavailable, search
19
+ `node_modules/@agent-native/core/docs` directly with `rg`.
20
+ 5. For app-specific rules, also read the app's own `AGENTS.md` and any relevant
21
+ `.agents/skills/<name>/SKILL.md`.
22
+
23
+ ## Useful Slugs
24
+
25
+ | Need | Slugs |
26
+ | --- | --- |
27
+ | Actions and typed client calls | `actions`, `client` |
28
+ | SQL, auth, access, sharing | `database`, `authentication`, `security`, `sharing` |
29
+ | UI state visible to the agent | `context-awareness` |
30
+ | Headless and chat-first apps | `pure-agent-apps`, `agent-surfaces`, `using-your-agent` |
31
+ | Automations and schedules | `automations`, `recurring-jobs` |
32
+ | Cross-app and external agents | `a2a-protocol`, `external-agents`, `mcp-protocol`, `mcp-apps` |
33
+ | Skills and instructions | `skills-guide`, `writing-agent-instructions` |
34
+
35
+ ## Don't
36
+
37
+ - Do not rely on memory for framework APIs when local package docs are present.
38
+ - Do not add custom REST wrappers for normal app data before reading `actions`.
39
+ - Do not add inline LLM calls before reading `using-your-agent` and
40
+ `agent-surfaces`.
@@ -305,7 +305,7 @@ A mail agent needs analytics data. The analytics agent exposes a "run-query" ski
305
305
 
306
306
  ```ts
307
307
  // In the mail agent's actions/get-analytics.ts
308
- import { defineAction } from "@agent-native/core/server";
308
+ import { defineAction } from "@agent-native/core/action";
309
309
  import { callAgent } from "@agent-native/core/a2a";
310
310
  import { z } from "zod";
311
311
 
@@ -19,11 +19,51 @@ One definition, seven consumers. This is rung 3 of the [ladder](/docs/what-is-ag
19
19
  If you are deciding whether to expose an operation headlessly, in chat, in an
20
20
  embedded sidecar, or as a full app screen, see [Agent Surfaces](/docs/agent-surfaces).
21
21
 
22
+ ## Start with one action {#hello-action}
23
+
24
+ The primitive-first on-ramp is one action, not a template. In a headless
25
+ scaffold such as `agent-native create my-agent --headless`, this can be the
26
+ whole first app:
27
+
28
+ ```ts
29
+ // actions/hello.ts
30
+ import { defineAction } from "@agent-native/core/action";
31
+ import { z } from "zod";
32
+
33
+ export default defineAction({
34
+ description: "Say hello from the local agent.",
35
+ schema: z.object({
36
+ name: z.string().default("world"),
37
+ }),
38
+ http: { method: "GET" },
39
+ readOnly: true,
40
+ run: async ({ name }) => {
41
+ return { message: `Hello, ${name}!` };
42
+ },
43
+ });
44
+ ```
45
+
46
+ Run it from the same folder:
47
+
48
+ ```bash
49
+ pnpm action hello --name Steve
50
+ ```
51
+
52
+ Then run the app-agent loop against the folder:
53
+
54
+ ```bash
55
+ pnpm agent "Call hello for Steve and explain the result"
56
+ ```
57
+
58
+ That is the same app-agent loop your scheduled jobs, chat UI, external MCP
59
+ tools, and future screens will use. Chat and domain templates are for adding UI
60
+ around actions, not a required prerequisite for the action itself.
61
+
22
62
  ## Defining an action {#defining}
23
63
 
24
64
  ```ts
25
65
  // actions/reply-to-email.ts
26
- import { defineAction } from "@agent-native/core";
66
+ import { defineAction } from "@agent-native/core/action";
27
67
  import { z } from "zod";
28
68
 
29
69
  export default defineAction({
@@ -229,7 +269,7 @@ User-owned tables must scope reads through `accessFilter` and writes through `as
229
269
 
230
270
  ```ts
231
271
  // actions/create-lead.ts
232
- import { defineAction } from "@agent-native/core";
272
+ import { defineAction } from "@agent-native/core/action";
233
273
  import { z } from "zod";
234
274
  import { getDb } from "../server/db/index.js";
235
275
  import * as schema from "../server/db/schema.js";
@@ -315,12 +355,12 @@ summaries, and insight cards; use [MCP Apps](/docs/mcp-apps) for inline UI in
315
355
  external MCP hosts.
316
356
 
317
357
  ```ts
358
+ import { defineAction } from "@agent-native/core/action";
359
+ import { ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER } from "@agent-native/core/action-ui";
318
360
  import {
319
- ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER,
361
+ createDataInsightsWidgetResult,
320
362
  dataInsightsWidgetResultSchema,
321
- defineAction,
322
- } from "@agent-native/core";
323
- import { createDataInsightsWidgetResult } from "@agent-native/core/data-widgets";
363
+ } from "@agent-native/core/data-widgets";
324
364
 
325
365
  export default defineAction({
326
366
  description: "Summarize response trends.",
@@ -411,7 +451,7 @@ Reads the current navigation state, fetches contextual data, and returns a snaps
411
451
 
412
452
  ```ts
413
453
  // actions/view-screen.ts
414
- import { defineAction } from "@agent-native/core";
454
+ import { defineAction } from "@agent-native/core/action";
415
455
  import { readAppState } from "@agent-native/core/application-state";
416
456
  import { z } from "zod";
417
457
 
@@ -438,7 +478,7 @@ Writes a one-shot navigation command to application state. The UI reads it, navi
438
478
 
439
479
  ```ts
440
480
  // actions/navigate.ts
441
- import { defineAction } from "@agent-native/core";
481
+ import { defineAction } from "@agent-native/core/action";
442
482
  import { writeAppState } from "@agent-native/core/application-state";
443
483
  import { z } from "zod";
444
484
 
@@ -13,13 +13,13 @@ application.
13
13
  The useful way to choose is not by protocol first. Choose the product surface
14
14
  you want, then use the matching primitive.
15
15
 
16
- | Surface | Use it when | Start with |
17
- | ----------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
18
- | **Headless agent/actions** | Code, jobs, scripts, another app, or another agent should call the work directly. | `defineAction`, HTTP, CLI, MCP, A2A |
19
- | **Rich chat on Agent-Native** | You want a standalone or embedded chat backed by the built-in agent loop. | `<AgentChatSurface>`, `<AssistantChat>`, `createAgentChatPlugin()` |
20
- | **Rich chat on your agent** | You built the agent elsewhere and want Agent-Native's composer, transcript, tool cards, and native widgets. | `AgentChatRuntime`, `<AssistantChat runtime={runtime}>` |
21
- | **Embedded sidecar** | You already have a SaaS app and want an agent beside it with page context and host commands. | `createAgentNativeEmbeddedPlugin()`, `AgentNativeEmbedded` |
22
- | **Full application** | Humans and agents should share durable screens, data, navigation, and collaboration. | Templates, actions, SQL state, context awareness |
16
+ | Surface | Use it when | Start with |
17
+ | ----------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
18
+ | **Headless agent/actions** | Code, jobs, scripts, another app, or another agent should call the work directly. | `agent-native create --headless`, `defineAction`, `agent-native agent`, HTTP, CLI, MCP, A2A |
19
+ | **Rich chat on Agent-Native** | You want a standalone or embedded chat backed by the built-in agent loop. | [Chat template](/docs/template-chat), `<AgentChatSurface>`, `<AssistantChat>` |
20
+ | **Rich chat on your agent** | You built the agent elsewhere and want Agent-Native's composer, transcript, tool cards, and native widgets. | `AgentChatRuntime`, `<AssistantChat runtime={runtime}>` |
21
+ | **Embedded sidecar** | You already have a SaaS app and want an agent beside it with page context and host commands. | `createAgentNativeEmbeddedPlugin()`, `AgentNativeEmbedded` |
22
+ | **Full application** | Humans and agents should share durable screens, data, navigation, and collaboration. | Templates, actions, SQL state, context awareness |
23
23
 
24
24
  Those are stages, not separate products. A workflow can start as a headless
25
25
  action, appear in chat as a table or chart, and later become a full screen in an
@@ -31,11 +31,19 @@ Use the headless path when no one needs to stare at a custom app screen while
31
31
  the work runs: scheduled jobs, integrations, backend workflows, CLI loops,
32
32
  another agent, or an existing product calling into Agent-Native.
33
33
 
34
- Most headless integrations should start with actions:
34
+ The smallest local path is a headless scaffold plus one action:
35
+
36
+ ```bash
37
+ npx @agent-native/core@latest create my-agent --headless
38
+ cd my-agent
39
+ pnpm install
40
+ ```
41
+
42
+ Then define the durable operation:
35
43
 
36
44
  ```ts
37
45
  // actions/summarize-week.ts
38
- import { defineAction } from "@agent-native/core";
46
+ import { defineAction } from "@agent-native/core/action";
39
47
  import { z } from "zod";
40
48
 
41
49
  export default defineAction({
@@ -52,14 +60,26 @@ One action is then callable as:
52
60
 
53
61
  - **HTTP** — `POST /_agent-native/actions/summarize-week`
54
62
  - **CLI** — `pnpm action summarize-week --formId form_123`
63
+ - **App-agent CLI** — `pnpm agent "Summarize form_123"`
55
64
  - **MCP** — from Claude, ChatGPT, Codex, Cursor, OpenCode, Copilot, and other MCP hosts
56
65
  - **A2A** — from another agent-native app or agent peer
57
66
  - **UI** — through `useActionQuery`, `useActionMutation`, or `callAction`
58
67
  - **Agent tool** — from the built-in chat loop
59
68
 
60
- If you need the whole agent loop headlessly, use the server API from a worker,
61
- job, integration webhook, or custom host. This is lower-level than actions: you
62
- provide the engine, model, messages, actions, and event sink yourself.
69
+ This is not a no-database or stateless mode. The app-agent loop stores sessions,
70
+ threads, runs, settings, credentials, application state, and share records in
71
+ SQL. Local development defaults to SQLite; hosted headless apps should use a
72
+ persistent SQL database.
73
+
74
+ If you need the whole agent loop headlessly from the project folder, use:
75
+
76
+ ```bash
77
+ pnpm agent "Summarize this week's forms."
78
+ ```
79
+
80
+ Workers, jobs, integration webhooks, and custom hosts can use the server API
81
+ directly. This is lower-level than actions: you provide the engine, model,
82
+ messages, actions, and event sink yourself.
63
83
 
64
84
  ```ts
65
85
  import {
@@ -97,11 +117,49 @@ For most apps, scheduled prompts and integration webhooks already call this loop
97
117
  for you. Reach for direct `runAgentLoop()` when you are building a custom
98
118
  headless host, eval runner, or server-side orchestration surface.
99
119
 
120
+ ### Running against a folder {#folder-loop}
121
+
122
+ If your goal is "run an agent against this folder," start with the app-agent
123
+ loop in that folder: scaffold the headless app, add actions/instructions, run
124
+ `pnpm agent "..."`. That keeps the work inside the same action/runtime/state
125
+ contract the app will use in production.
126
+
127
+ External coding harnesses are a separate product surface for embedding Claude
128
+ Code, Codex, Pi, Cursor, Mastra, or similar runtimes inside an Agent-Native app.
129
+ Use them when you are building a coding-agent product, not as the default way to
130
+ start a local agent-native workflow.
131
+
132
+ ### Cloud repo access {#cloud-repo-access}
133
+
134
+ For cloud headless apps that need repository access, the planned model is a
135
+ GitHub connector plus token CRUD: list repositories, search files, read files,
136
+ create or edit files, delete files, and revoke access through provider-scoped
137
+ credentials.
138
+
139
+ Do not treat a VM clone or long-lived sandbox checkout as the primary cloud
140
+ repo-access model. Sandboxes still matter for isolated code execution, but
141
+ repository access should be explicit, permissioned, auditable, and revocable
142
+ through the connector layer.
143
+
144
+ ### Sharing sessions and runs {#sharing-runs}
145
+
146
+ Headless sessions and runs are durable objects. Shareability should be phased:
147
+ read/share links first, so teammates can inspect sanitized prompts, outputs,
148
+ and run status; permissioned writable collaboration later, so continuing a run,
149
+ approving actions, editing schedules, or changing configuration goes through
150
+ explicit access checks.
151
+
100
152
  ## Rich chat on Agent-Native {#rich-chat}
101
153
 
102
154
  Use the built-in chat when the user should talk to the agent, see tool calls,
103
155
  approve work, inspect native results, and keep a durable thread history.
104
156
 
157
+ For a full app starting point, use the [Chat template](/docs/template-chat):
158
+
159
+ ```bash
160
+ npx @agent-native/core@latest create my-chat-app --template chat
161
+ ```
162
+
105
163
  The simplest full-page chat:
106
164
 
107
165
  ```tsx
@@ -131,6 +189,9 @@ components in the chat, without iframes. See [Native Chat UI](/docs/native-chat-
131
189
  Use this path when your agent is already built with another framework or
132
190
  runtime and you want Agent-Native's chat UI around it.
133
191
 
192
+ The [Chat template](/docs/template-chat) is still useful here: keep its app
193
+ shell and thread UI, then swap the runtime behind the chat plugin or route.
194
+
134
195
  `AgentChatRuntime` is the boundary. Your runtime streams normalized events;
135
196
  Agent-Native renders the composer, transcript, tool calls, approvals, native
136
197
  widgets, and app layout.
@@ -245,8 +306,9 @@ Full apps add product UI around the same action and agent contract:
245
306
  - **Deep links** — action results can open the right app view.
246
307
  - **Native chat widgets** — tables, charts, cards, approvals, and typed results appear inline.
247
308
 
248
- Start from a [template](/docs/cloneable-saas) when you want a complete app, or
249
- from [Starter](/docs/template-starter) when you want only the framework wiring.
309
+ Start from the [Chat template](/docs/template-chat) when you want a minimal app
310
+ around your actions, or from a domain [template](/docs/cloneable-saas) when you
311
+ want a complete product shape.
250
312
 
251
313
  ## How to choose {#how-to-choose}
252
314
 
@@ -228,7 +228,7 @@ Actions can use CLI adapters directly for structured access:
228
228
 
229
229
  ```ts
230
230
  // actions/list-prs.ts
231
- import { defineAction } from "@agent-native/core/server";
231
+ import { defineAction } from "@agent-native/core/action";
232
232
  import { ShellCliAdapter } from "@agent-native/core/adapters/cli";
233
233
  import { z } from "zod";
234
234
 
@@ -15,6 +15,7 @@ Each one is a real app you could use today, and the launching pad for your own v
15
15
 
16
16
  | Template | What it is |
17
17
  | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
18
+ | [**Chat**](/docs/template-chat) | Minimal chat-first app with durable threads, actions, auth, and a clean path to custom UI or your own backend. |
18
19
  | [**Mail**](/docs/template-mail) | An agent-native Superhuman. Inbox, labels, AI triage, keyboard-first, drafts and sends through the agent. |
19
20
  | [**Calendar**](/docs/template-calendar) | An agent-native Google Calendar. Events, sync, public booking links, agent-driven scheduling. |
20
21
  | [**Content**](/docs/template-content) | Open-source Obsidian for MDX. Local Markdown/MDX, Tiptap editor, Notion sync, real-time multi-user collab. |
@@ -29,7 +30,7 @@ Each one is a real app you could use today, and the launching pad for your own v
29
30
  | [**Plan**](/docs/template-plan) | Visual plans and PR recaps with diagrams, wireframes, and annotations. |
30
31
  | [**Dispatch**](/docs/template-dispatch) | The workspace control plane: shared secrets, reusable integrations, Slack/Telegram, scheduled jobs. |
31
32
 
32
- Don't want a domain template? See [Pure-Agent Apps / Starter](/docs/pure-agent-apps) for the minimal scaffold.
33
+ Don't want a domain template? Use [Chat](/docs/template-chat) when you want a basic app users can talk to immediately, or start action-first with [Pure-Agent Apps](/docs/pure-agent-apps).
33
34
 
34
35
  See the full catalog under [Templates](/templates), or jump straight to one — for example, [Dispatch](/docs/template-dispatch) is a great place to start if you want a workspace-style app.
35
36
 
@@ -72,11 +73,11 @@ You don't have to. Every template is also available as a hosted app on `agent-na
72
73
 
73
74
  ## Try it with a skill {#try-with-a-skill}
74
75
 
75
- Not ready to scaffold? You can add agent-native superpowers to a coding agent you already use with a single command — no app needed. See [Try it with a skill](/docs/getting-started#try-with-a-skill) in Getting Started.
76
+ Not ready to scaffold? You can add agent-native superpowers to a coding agent you already use with a single command — no app needed. See the [Skills Guide](/docs/skills-guide#app-backed-skills).
76
77
 
77
78
  ## Building on this
78
79
 
79
- - [**Getting Started**](/docs/getting-started) — clone your first template and run it locally
80
+ - [**Getting Started**](/docs/getting-started) — create a minimal chat app or headless action
80
81
  - [**Messaging the agent**](/docs/messaging) — how users (and you) talk to the agent that ships with each template
81
82
  - [**Multi-App Workspace**](/docs/multi-app-workspace) — bundle several templates into one workspace that shares auth, brand, and agent
82
83
  - [**Dispatch**](/docs/template-dispatch) — the workspace control plane template
@@ -90,7 +91,7 @@ If you're scaffolding now, the CLI command is:
90
91
  npx @agent-native/core@latest create my-platform
91
92
  ```
92
93
 
93
- You'll get a multi-select picker. Pick one app (standalone) or several (workspace — apps share auth, brand, agent config, and database). Each picked template is scaffolded into `apps/<name>/` with every file you need.
94
+ You'll get a multi-select picker. Pick one app (standalone) or several (workspace — apps share auth, brand, agent config, and database). Each picked template is scaffolded into `apps/<name>/` with every file you need. For an action-only app instead of a template UI, use `npx @agent-native/core@latest create my-agent --headless`.
94
95
 
95
96
  Fill in `.env` (mostly `ANTHROPIC_API_KEY` and `DATABASE_URL`), `pnpm install`, `pnpm dev`, and it works. No "TODO: implement login," no placeholder routes.
96
97