@agent-native/core 0.7.4 → 0.7.7

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 (250) hide show
  1. package/README.md +6 -5
  2. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  3. package/dist/agent/engine/anthropic-engine.js +8 -4
  4. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  5. package/dist/agent/engine/types.d.ts +1 -1
  6. package/dist/agent/engine/types.d.ts.map +1 -1
  7. package/dist/agent/production-agent.d.ts +7 -0
  8. package/dist/agent/production-agent.d.ts.map +1 -1
  9. package/dist/agent/production-agent.js +153 -118
  10. package/dist/agent/production-agent.js.map +1 -1
  11. package/dist/agent/run-manager.d.ts +4 -0
  12. package/dist/agent/run-manager.d.ts.map +1 -1
  13. package/dist/agent/run-manager.js +46 -25
  14. package/dist/agent/run-manager.js.map +1 -1
  15. package/dist/agent/run-store.d.ts +12 -3
  16. package/dist/agent/run-store.d.ts.map +1 -1
  17. package/dist/agent/run-store.js +25 -4
  18. package/dist/agent/run-store.js.map +1 -1
  19. package/dist/chat-threads/store.d.ts +13 -0
  20. package/dist/chat-threads/store.d.ts.map +1 -1
  21. package/dist/chat-threads/store.js +66 -10
  22. package/dist/chat-threads/store.js.map +1 -1
  23. package/dist/cli/create.d.ts.map +1 -1
  24. package/dist/cli/create.js +8 -1
  25. package/dist/cli/create.js.map +1 -1
  26. package/dist/cli/index.js +8 -0
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/cli/info.d.ts +2 -0
  29. package/dist/cli/info.d.ts.map +1 -0
  30. package/dist/cli/info.js +103 -0
  31. package/dist/cli/info.js.map +1 -0
  32. package/dist/client/AssistantChat.d.ts.map +1 -1
  33. package/dist/client/AssistantChat.js +249 -85
  34. package/dist/client/AssistantChat.js.map +1 -1
  35. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  36. package/dist/client/agent-chat-adapter.js +12 -1
  37. package/dist/client/agent-chat-adapter.js.map +1 -1
  38. package/dist/client/composer/TiptapComposer.d.ts +3 -1
  39. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  40. package/dist/client/composer/TiptapComposer.js +46 -2
  41. package/dist/client/composer/TiptapComposer.js.map +1 -1
  42. package/dist/client/composer/VoiceButton.d.ts +21 -0
  43. package/dist/client/composer/VoiceButton.d.ts.map +1 -0
  44. package/dist/client/composer/VoiceButton.js +51 -0
  45. package/dist/client/composer/VoiceButton.js.map +1 -0
  46. package/dist/client/composer/useVoiceDictation.d.ts +38 -0
  47. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -0
  48. package/dist/client/composer/useVoiceDictation.js +398 -0
  49. package/dist/client/composer/useVoiceDictation.js.map +1 -0
  50. package/dist/client/onboarding/OnboardingPanel.js +2 -2
  51. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  52. package/dist/client/org/OrgSwitcher.d.ts +5 -4
  53. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  54. package/dist/client/org/OrgSwitcher.js +90 -24
  55. package/dist/client/org/OrgSwitcher.js.map +1 -1
  56. package/dist/client/resources/McpServerDetail.d.ts +15 -0
  57. package/dist/client/resources/McpServerDetail.d.ts.map +1 -0
  58. package/dist/client/resources/McpServerDetail.js +65 -0
  59. package/dist/client/resources/McpServerDetail.js.map +1 -0
  60. package/dist/client/resources/ResourceEditor.js +1 -1
  61. package/dist/client/resources/ResourceEditor.js.map +1 -1
  62. package/dist/client/resources/ResourceTree.d.ts +6 -1
  63. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  64. package/dist/client/resources/ResourceTree.js +18 -7
  65. package/dist/client/resources/ResourceTree.js.map +1 -1
  66. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  67. package/dist/client/resources/ResourcesPanel.js +191 -20
  68. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  69. package/dist/client/resources/use-mcp-servers.d.ts +68 -0
  70. package/dist/client/resources/use-mcp-servers.d.ts.map +1 -0
  71. package/dist/client/resources/use-mcp-servers.js +83 -0
  72. package/dist/client/resources/use-mcp-servers.js.map +1 -0
  73. package/dist/client/resources/use-resources.d.ts +39 -1
  74. package/dist/client/resources/use-resources.d.ts.map +1 -1
  75. package/dist/client/resources/use-resources.js +102 -0
  76. package/dist/client/resources/use-resources.js.map +1 -1
  77. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  78. package/dist/client/settings/SettingsPanel.js +3 -2
  79. package/dist/client/settings/SettingsPanel.js.map +1 -1
  80. package/dist/client/settings/VoiceTranscriptionSection.d.ts +14 -0
  81. package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -0
  82. package/dist/client/settings/VoiceTranscriptionSection.js +111 -0
  83. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -0
  84. package/dist/client/sharing/ShareButton.d.ts +6 -4
  85. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  86. package/dist/client/sharing/ShareButton.js +299 -34
  87. package/dist/client/sharing/ShareButton.js.map +1 -1
  88. package/dist/client/sharing/ShareDialog.d.ts +22 -4
  89. package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
  90. package/dist/client/sharing/ShareDialog.js +170 -148
  91. package/dist/client/sharing/ShareDialog.js.map +1 -1
  92. package/dist/client/sharing/VisibilityBadge.d.ts.map +1 -1
  93. package/dist/client/sharing/VisibilityBadge.js +1 -2
  94. package/dist/client/sharing/VisibilityBadge.js.map +1 -1
  95. package/dist/client/use-action.d.ts.map +1 -1
  96. package/dist/client/use-action.js +20 -1
  97. package/dist/client/use-action.js.map +1 -1
  98. package/dist/db/migrations.d.ts +18 -3
  99. package/dist/db/migrations.d.ts.map +1 -1
  100. package/dist/db/migrations.js +25 -3
  101. package/dist/db/migrations.js.map +1 -1
  102. package/dist/deploy/workspace-core.js +2 -2
  103. package/dist/mcp-client/config.d.ts +20 -1
  104. package/dist/mcp-client/config.d.ts.map +1 -1
  105. package/dist/mcp-client/config.js +28 -11
  106. package/dist/mcp-client/config.js.map +1 -1
  107. package/dist/mcp-client/hub-client.d.ts +38 -0
  108. package/dist/mcp-client/hub-client.d.ts.map +1 -0
  109. package/dist/mcp-client/hub-client.js +147 -0
  110. package/dist/mcp-client/hub-client.js.map +1 -0
  111. package/dist/mcp-client/hub-routes.d.ts +42 -0
  112. package/dist/mcp-client/hub-routes.d.ts.map +1 -0
  113. package/dist/mcp-client/hub-routes.js +114 -0
  114. package/dist/mcp-client/hub-routes.js.map +1 -0
  115. package/dist/mcp-client/index.d.ts +15 -0
  116. package/dist/mcp-client/index.d.ts.map +1 -1
  117. package/dist/mcp-client/index.js +35 -0
  118. package/dist/mcp-client/index.js.map +1 -1
  119. package/dist/mcp-client/manager.d.ts +54 -8
  120. package/dist/mcp-client/manager.d.ts.map +1 -1
  121. package/dist/mcp-client/manager.js +276 -59
  122. package/dist/mcp-client/manager.js.map +1 -1
  123. package/dist/mcp-client/remote-store.d.ts +102 -0
  124. package/dist/mcp-client/remote-store.d.ts.map +1 -0
  125. package/dist/mcp-client/remote-store.js +200 -0
  126. package/dist/mcp-client/remote-store.js.map +1 -0
  127. package/dist/mcp-client/routes.d.ts +55 -0
  128. package/dist/mcp-client/routes.d.ts.map +1 -0
  129. package/dist/mcp-client/routes.js +384 -0
  130. package/dist/mcp-client/routes.js.map +1 -0
  131. package/dist/mcp-client/visibility.d.ts +16 -0
  132. package/dist/mcp-client/visibility.d.ts.map +1 -0
  133. package/dist/mcp-client/visibility.js +45 -0
  134. package/dist/mcp-client/visibility.js.map +1 -0
  135. package/dist/org/context.js +2 -2
  136. package/dist/org/context.js.map +1 -1
  137. package/dist/org/handlers.js +2 -2
  138. package/dist/org/handlers.js.map +1 -1
  139. package/dist/resources/handlers.d.ts.map +1 -1
  140. package/dist/resources/handlers.js +30 -0
  141. package/dist/resources/handlers.js.map +1 -1
  142. package/dist/secrets/register-framework-secrets.d.ts +13 -0
  143. package/dist/secrets/register-framework-secrets.d.ts.map +1 -0
  144. package/dist/secrets/register-framework-secrets.js +59 -0
  145. package/dist/secrets/register-framework-secrets.js.map +1 -0
  146. package/dist/secrets/register.d.ts.map +1 -1
  147. package/dist/secrets/register.js +8 -1
  148. package/dist/secrets/register.js.map +1 -1
  149. package/dist/server/action-routes.d.ts.map +1 -1
  150. package/dist/server/action-routes.js +22 -2
  151. package/dist/server/action-routes.js.map +1 -1
  152. package/dist/server/agent-chat-plugin.d.ts +16 -0
  153. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  154. package/dist/server/agent-chat-plugin.js +237 -70
  155. package/dist/server/agent-chat-plugin.js.map +1 -1
  156. package/dist/server/app-url.d.ts.map +1 -1
  157. package/dist/server/app-url.js +11 -3
  158. package/dist/server/app-url.js.map +1 -1
  159. package/dist/server/auth.d.ts.map +1 -1
  160. package/dist/server/auth.js +50 -0
  161. package/dist/server/auth.js.map +1 -1
  162. package/dist/server/better-auth-instance.d.ts.map +1 -1
  163. package/dist/server/better-auth-instance.js +99 -4
  164. package/dist/server/better-auth-instance.js.map +1 -1
  165. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  166. package/dist/server/core-routes-plugin.js +44 -0
  167. package/dist/server/core-routes-plugin.js.map +1 -1
  168. package/dist/server/create-server.d.ts.map +1 -1
  169. package/dist/server/create-server.js +6 -0
  170. package/dist/server/create-server.js.map +1 -1
  171. package/dist/server/date-utils.d.ts +15 -0
  172. package/dist/server/date-utils.d.ts.map +1 -0
  173. package/dist/server/date-utils.js +41 -0
  174. package/dist/server/date-utils.js.map +1 -0
  175. package/dist/server/index.d.ts +2 -1
  176. package/dist/server/index.d.ts.map +1 -1
  177. package/dist/server/index.js +2 -1
  178. package/dist/server/index.js.map +1 -1
  179. package/dist/server/onboarding-html.d.ts +3 -0
  180. package/dist/server/onboarding-html.d.ts.map +1 -1
  181. package/dist/server/onboarding-html.js +13 -3
  182. package/dist/server/onboarding-html.js.map +1 -1
  183. package/dist/server/request-context.d.ts +9 -0
  184. package/dist/server/request-context.d.ts.map +1 -1
  185. package/dist/server/request-context.js +10 -0
  186. package/dist/server/request-context.js.map +1 -1
  187. package/dist/server/transcribe-voice.d.ts +26 -0
  188. package/dist/server/transcribe-voice.d.ts.map +1 -0
  189. package/dist/server/transcribe-voice.js +143 -0
  190. package/dist/server/transcribe-voice.js.map +1 -0
  191. package/dist/styles/agent-native.css +111 -0
  192. package/dist/tailwind.preset.d.ts +2 -2
  193. package/dist/tailwind.preset.d.ts.map +1 -1
  194. package/dist/tailwind.preset.js +27 -7
  195. package/dist/tailwind.preset.js.map +1 -1
  196. package/dist/templates/default/app/global.css +65 -68
  197. package/dist/templates/default/components.json +1 -1
  198. package/dist/templates/default/package.json +2 -4
  199. package/dist/templates/default/vite.config.ts +3 -0
  200. package/dist/templates/workspace-core/package.json +1 -4
  201. package/dist/templates/workspace-core/src/index.ts +1 -1
  202. package/dist/templates/workspace-core/styles/tokens.css +22 -0
  203. package/dist/templates/workspace-core/tsconfig.json +1 -1
  204. package/dist/vite/client.d.ts +6 -0
  205. package/dist/vite/client.d.ts.map +1 -1
  206. package/dist/vite/client.js +18 -1
  207. package/dist/vite/client.js.map +1 -1
  208. package/docs/content/actions.md +169 -74
  209. package/docs/content/agent-teams.md +139 -0
  210. package/docs/content/cloneable-saas.md +98 -0
  211. package/docs/content/creating-templates.md +9 -11
  212. package/docs/content/deployment.md +2 -9
  213. package/docs/content/drop-in-agent.md +200 -0
  214. package/docs/content/enterprise-workspace.md +22 -10
  215. package/docs/content/getting-started.md +34 -19
  216. package/docs/content/integrations.md +3 -3
  217. package/docs/content/key-concepts.md +50 -23
  218. package/docs/content/mcp-clients.md +71 -0
  219. package/docs/content/pure-agent-apps.md +69 -0
  220. package/docs/content/recurring-jobs.md +123 -0
  221. package/docs/content/skills-guide.md +8 -0
  222. package/docs/content/template-analytics.md +190 -0
  223. package/docs/content/template-calendar.md +151 -0
  224. package/docs/content/template-clips.md +55 -0
  225. package/docs/content/template-content.md +141 -0
  226. package/docs/content/template-dispatch.md +58 -0
  227. package/docs/content/template-forms.md +51 -0
  228. package/docs/content/template-mail.md +169 -0
  229. package/docs/content/template-slides.md +218 -0
  230. package/docs/content/template-starter.md +68 -0
  231. package/docs/content/template-video.md +162 -0
  232. package/docs/content/voice-input.md +59 -0
  233. package/docs/content/what-is-agent-native.md +142 -45
  234. package/docs/content/workspace-management.md +1 -0
  235. package/docs/content/{resources.md → workspace.md} +94 -42
  236. package/package.json +9 -16
  237. package/src/templates/default/app/global.css +65 -68
  238. package/src/templates/default/components.json +1 -1
  239. package/src/templates/default/package.json +2 -4
  240. package/src/templates/default/vite.config.ts +3 -0
  241. package/src/templates/workspace-core/package.json +1 -4
  242. package/src/templates/workspace-core/src/index.ts +1 -1
  243. package/src/templates/workspace-core/styles/tokens.css +22 -0
  244. package/src/templates/workspace-core/tsconfig.json +1 -1
  245. package/dist/templates/default/postcss.config.js +0 -6
  246. package/dist/templates/default/tailwind.config.ts +0 -7
  247. package/dist/templates/workspace-core/tailwind.preset.ts +0 -34
  248. package/src/templates/default/postcss.config.js +0 -6
  249. package/src/templates/default/tailwind.config.ts +0 -7
  250. package/src/templates/workspace-core/tailwind.preset.ts +0 -34
@@ -0,0 +1,200 @@
1
+ ---
2
+ title: "Drop-in Agent"
3
+ description: "Mount the agent chat + workspace into any React app with <AgentPanel>, <AgentSidebar>, and sendToAgentChat()."
4
+ ---
5
+
6
+ # Drop-in Agent
7
+
8
+ You don't need to build agent-native from scratch. The agent chat, workspace tab, CLI terminal, voice input, and all the related infrastructure ship as a handful of React components you drop into any app.
9
+
10
+ > **Prerequisite:** the server has to be running the `agent-chat-plugin` (it auto-mounts in every template). If you're starting from scratch, see [Server](/docs/server).
11
+
12
+ ## The components at a glance {#components}
13
+
14
+ | Component | What it is | Use it when |
15
+ | --------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------- |
16
+ | `<AgentSidebar>` | Wraps your app, adds a toggleable side panel containing the full agent | You want the agent available alongside your app on every screen |
17
+ | `<AgentToggleButton>` | Opens/closes `<AgentSidebar>` (put it in your header) | Pair with `<AgentSidebar>` |
18
+ | `<AgentPanel>` | The raw panel itself — chat + CLI + workspace tabs | You want full control over layout, or a dedicated agent page |
19
+ | `sendToAgentChat()` | Programmatically send a message to the chat | A button that hands work to the agent instead of running inline |
20
+ | `useActionMutation()` | Typesafe frontend wrapper around an action | The UI needs to run the same operation an agent tool would run |
21
+
22
+ All of these are exported from `@agent-native/core/client`.
23
+
24
+ ## The 80% case: `<AgentSidebar>` {#sidebar}
25
+
26
+ The most common setup is a sidebar that slides in from the right on any screen. Two pieces — the wrapper and a header button:
27
+
28
+ ```tsx
29
+ // app/root.tsx
30
+ import { AgentSidebar, AgentToggleButton } from "@agent-native/core/client";
31
+
32
+ export default function Root() {
33
+ return (
34
+ <AgentSidebar
35
+ emptyStateText="How can I help?"
36
+ suggestions={[
37
+ "Summarize my inbox",
38
+ "Draft a reply to the latest email",
39
+ "Show me yesterday's signup numbers",
40
+ ]}
41
+ sidebarWidth={420}
42
+ position="right"
43
+ >
44
+ <YourApp />
45
+ </AgentSidebar>
46
+ );
47
+ }
48
+
49
+ // somewhere in your header / navbar
50
+ <AgentToggleButton />;
51
+ ```
52
+
53
+ That's it. The user now has a toggleable agent on every page — with chat history, workspace tab, CLI terminal, voice input, and a fullscreen mode. State persists across reloads via `localStorage`.
54
+
55
+ ### Props
56
+
57
+ - **`children`** — your app. Rendered in the main area; the sidebar overlays from the chosen side.
58
+ - **`emptyStateText`** — greeting shown when the chat has no messages. Default: `"How can I help you?"`.
59
+ - **`suggestions`** — starter prompts rendered as clickable chips when empty.
60
+ - **`sidebarWidth`** — pixel width. Default: `380`.
61
+ - **`position`** — `"left"` or `"right"`. Default: `"right"`.
62
+ - **`defaultOpen`** — whether the sidebar starts open (desktop only). Default: `false`.
63
+
64
+ ## The other 20%: `<AgentPanel>` {#panel}
65
+
66
+ When you need full control over layout — a dedicated `/chat` route, an embedded panel in a side column you manage, or a popup — render `<AgentPanel>` directly:
67
+
68
+ ```tsx
69
+ // app/routes/agent.tsx
70
+ import { AgentPanel } from "@agent-native/core/client";
71
+
72
+ export default function AgentRoute() {
73
+ return (
74
+ <div className="h-screen">
75
+ <AgentPanel defaultMode="chat" className="h-full" />
76
+ </div>
77
+ );
78
+ }
79
+ ```
80
+
81
+ `<AgentPanel>` gives you the raw tabs (Chat / CLI / Workspace) without the sidebar wrapper, the collapse button, or any state persistence. Put it wherever you want; you handle the layout.
82
+
83
+ ### Selected props
84
+
85
+ - **`defaultMode`** — `"chat"` or `"cli"`. Default: `"chat"`.
86
+ - **`className`** — CSS class for the outer container.
87
+ - **`onCollapse`** — if provided, a collapse button appears in the header.
88
+ - **`isFullscreen`** / **`onToggleFullscreen`** — wire up external fullscreen state if you want a Claude-style centered column.
89
+ - **`storageKey`** — namespace for `localStorage` keys. Useful when you render multiple panels (different app instances or workspaces) in the same page.
90
+
91
+ Full props: `AgentPanelProps` in `@agent-native/core/client`.
92
+
93
+ ## Programmatic messages: `sendToAgentChat()` {#send}
94
+
95
+ 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)):
96
+
97
+ ```tsx
98
+ import { sendToAgentChat } from "@agent-native/core/client";
99
+
100
+ <Button
101
+ onClick={() =>
102
+ sendToAgentChat({
103
+ message: "Generate a chart showing signups by source",
104
+ context: `Dashboard ID: ${dashboardId}, date range: last 30 days`,
105
+ submit: true,
106
+ })
107
+ }
108
+ >
109
+ Generate chart
110
+ </Button>;
111
+ ```
112
+
113
+ ### Options
114
+
115
+ - **`message`** — the visible prompt shown in chat.
116
+ - **`context`** — hidden context appended to the prompt (selected text, cursor position, current entity id — anything the agent should know but the user shouldn't see twice).
117
+ - **`submit`** — `true` to auto-run, `false` to prefill but wait. Omit to use the project default.
118
+ - **`openSidebar`** — set to `false` for background/silent sends. Default opens the sidebar so the user sees the response.
119
+ - **`type`** — `"content"` (default) keeps the work in the embedded app agent. `"code"` routes to the code-editing frame (for agent-written code changes, see [Frames](/docs/frames)).
120
+
121
+ `sendToAgentChat` returns a stable `tabId` you can use to track the chat run.
122
+
123
+ If you want a loading state, use the `useSendToAgentChat()` hook — it returns both `send` and `isGenerating`:
124
+
125
+ ```ts
126
+ import { useSendToAgentChat } from "@agent-native/core/client";
127
+
128
+ const { send, isGenerating } = useSendToAgentChat();
129
+ ```
130
+
131
+ ## Typesafe actions from the UI: `useActionMutation()` {#use-action-mutation}
132
+
133
+ When the UI needs to run the same operation an agent tool would run — the fourth rung of the [ladder](/docs/what-is-agent-native#rung-three) — use `useActionMutation`:
134
+
135
+ ```tsx
136
+ import { useActionMutation } from "@agent-native/core/client";
137
+
138
+ const { mutate, isPending } = useActionMutation("replyToEmail");
139
+
140
+ <Button onClick={() => mutate({ emailId, body: "Thanks!" })}>
141
+ Send Reply
142
+ </Button>;
143
+ ```
144
+
145
+ Type-safe arguments come from the zod schema in your `defineAction()`. See [Actions](/docs/actions) for the full action system.
146
+
147
+ ## Selection + cursor awareness {#selection}
148
+
149
+ The agent can see what the user has selected — text, cells, slides, contacts — via the `navigation` and `selection` keys in application state. If you'd like Cmd-I (or similar) to send a selected range into the chat as context, see [Context Awareness](/docs/context-awareness).
150
+
151
+ ## Putting it all together {#putting-it-together}
152
+
153
+ A typical drop-in setup:
154
+
155
+ ```tsx
156
+ // app/root.tsx
157
+ import {
158
+ AgentSidebar,
159
+ AgentToggleButton,
160
+ sendToAgentChat,
161
+ } from "@agent-native/core/client";
162
+
163
+ export default function Root() {
164
+ return (
165
+ <AgentSidebar suggestions={["Draft a reply", "Summarize selection"]}>
166
+ <Header>
167
+ <AgentToggleButton />
168
+ </Header>
169
+
170
+ <Main>
171
+ <YourRoutes />
172
+ </Main>
173
+ </AgentSidebar>
174
+ );
175
+ }
176
+ ```
177
+
178
+ ```tsx
179
+ // Anywhere else in the app
180
+ <Button
181
+ onClick={() =>
182
+ sendToAgentChat({
183
+ message: "Summarize this thread",
184
+ context: `Thread id: ${threadId}`,
185
+ submit: true,
186
+ })
187
+ }
188
+ >
189
+ Summarize
190
+ </Button>
191
+ ```
192
+
193
+ The user sees a chat button in the header, can open it, and can talk to the agent. Your buttons hand work to that same agent instead of running one-shot LLM calls.
194
+
195
+ ## What's next
196
+
197
+ - [**Actions**](/docs/actions) — `defineAction()` and `useActionMutation()`
198
+ - [**Context Awareness**](/docs/context-awareness) — selection, navigation, view-screen
199
+ - [**Workspace**](/docs/workspace) — what the Workspace tab contains (skills, memory, MCP servers, scheduled jobs)
200
+ - [**Voice Input**](/docs/voice-input) — the microphone in the chat composer
@@ -24,7 +24,7 @@ Anything every app in your org should agree on lives in the workspace core:
24
24
  | Agent skills | `skills/<skill-name>/SKILL.md` |
25
25
  | Shared agent actions | `actions/*.ts` |
26
26
  | Shared React components | `src/client/*.tsx` (e.g. `AuthenticatedLayout`) |
27
- | Design tokens / brand | `tailwind.preset.ts` |
27
+ | Design tokens / brand | `styles/tokens.css` |
28
28
  | Shared API credentials | `src/credentials.ts` → `resolveCompanyCredential()` |
29
29
 
30
30
  Each individual app becomes _just a set of screens_ — routes, dashboards, views, domain-specific actions. Everything else is inherited. If you're building ten tools for the same org, nine of them are 80% the same package, and the workspace core is where that 80% lives.
@@ -56,7 +56,7 @@ my-company-platform/
56
56
  │ ├── actions/ # shared agent-callable actions
57
57
  │ ├── skills/ # shared agent skills
58
58
  │ ├── AGENTS.md # enterprise-wide instructions
59
- │ └── tailwind.preset.ts # brand tokens
59
+ │ └── styles/tokens.css # brand tokens (Tailwind v4 @theme + CSS vars)
60
60
  └── apps/
61
61
  ├── mail/
62
62
  ├── calendar/
@@ -159,6 +159,14 @@ A few onboarding flows are workspace-aware out of the box:
159
159
  - **Builder `/cli-auth`**: clicking "Connect Builder" from any app writes `BUILDER_PRIVATE_KEY` and friends to the **workspace root** `.env`, so every app gains browser access at once.
160
160
  - **Env-vars settings route** (`POST /_agent-native/env-vars`): when inside a workspace, defaults to writing the workspace root `.env`. Pass `scope: "app"` in the body to override one app.
161
161
 
162
+ ## Shared MCP servers {#shared-mcp}
163
+
164
+ Drop an `mcp.config.json` at the workspace root and every app in the workspace connects to the same MCP servers — one place to configure `claude-in-chrome`, `@modelcontextprotocol/server-filesystem`, Playwright, or any internal MCP server. Individual apps can override with their own `mcp.config.json` (app-root wins over the workspace root for that one app).
165
+
166
+ For remote HTTP MCP servers (Zapier, Composio, internal tools), users can add them from the settings UI at **Personal** or **Team (org)** scope — no file edits, hot-reloaded into the running agent. And if you run the dispatch template, it can act as an **MCP hub** that every other app in the workspace pulls org-scope servers from, so you configure each URL + bearer token exactly once.
167
+
168
+ See [MCP Clients](/docs/mcp-clients) for the config schema, precedence rules, remote-UI scopes, and hub setup.
169
+
162
170
  ## Shared credentials {#shared-credentials}
163
171
 
164
172
  Rotate a third-party API key in one place and every app picks it up:
@@ -173,18 +181,22 @@ Under the hood this wraps `@agent-native/core`'s `resolveCredential()`, which ch
173
181
 
174
182
  ## Shared design tokens {#design-tokens}
175
183
 
176
- The core exports a Tailwind preset. Each app's `tailwind.config.ts` extends it:
184
+ The framework is on Tailwind v4. The core ships a shared CSS file with the standard `@theme` tokens — each app imports it from its `app/global.css`:
177
185
 
178
- ```ts
179
- import preset from "@my-company-platform/core-module/tailwind";
186
+ ```css
187
+ @import "tailwindcss";
188
+ @import "@my-company-platform/core-module/styles/tokens.css";
189
+ @source "./**/*.{ts,tsx}";
180
190
 
181
- export default {
182
- presets: [preset],
183
- content: ["./app/**/*.{ts,tsx}"],
184
- };
191
+ :root {
192
+ --background: 0 0% 100%; /* ...brand tokens... */
193
+ }
194
+ .dark {
195
+ --background: 220 6% 6%; /* ... */
196
+ }
185
197
  ```
186
198
 
187
- Brand colors, typography, spacing scales, and any shared component classes live in one file. Update it in the core and every app rebrands on the next build. Shared React components in `src/client/` pick up the same tokens automatically.
199
+ Brand colors, typography, spacing scales, and any shared component classes live in that one CSS file. Update it in the core and every app rebrands on the next build. Shared React components in `src/client/` pick up the same tokens automatically.
188
200
 
189
201
  ## Deployment {#deployment}
190
202
 
@@ -5,7 +5,7 @@ description: "Pick a template, create your app, and start customizing it with AI
5
5
 
6
6
  # Getting Started
7
7
 
8
- The fastest way to get started is to pick a template and customize it. Templates are complete, production-ready apps not starter kits. You get a working app in under a minute and start making it yours.
8
+ The fastest way to get started is to pick a template and make it yours. Agent-native templates are **[cloneable SaaS](/docs/cloneable-saas)** — complete, production-grade apps, not starter kits. You get a working product in under a minute and start customizing it with the agent.
9
9
 
10
10
  ## Create Your Workspace {#create-your-app}
11
11
 
@@ -41,16 +41,19 @@ From here, use your AI coding tool (Claude Code, Cursor, Windsurf, etc.) to cust
41
41
 
42
42
  Each template is a complete app with UI, agent actions, database schema, and AI instructions ready to go:
43
43
 
44
- | Template | Replaces |
45
- | --------------------------------- | --------------------------- |
46
- | [Mail](/templates/mail) | Superhuman, Gmail |
47
- | [Calendar](/templates/calendar) | Google Calendar, Calendly |
48
- | [Content](/templates/content) | Notion, Google Docs |
49
- | [Slides](/templates/slides) | Google Slides, Pitch |
50
- | [Video](/templates/video) | video editing |
51
- | [Analytics](/templates/analytics) | Amplitude, Mixpanel, Looker |
44
+ | Template | Replaces |
45
+ | ----------------------------------- | ------------------------------------------------ |
46
+ | [Mail](/templates/mail) | Superhuman, Gmail |
47
+ | [Calendar](/templates/calendar) | Google Calendar, Calendly |
48
+ | [Content](/templates/content) | Notion, Google Docs |
49
+ | [Slides](/templates/slides) | Google Slides, Pitch |
50
+ | [Video](/templates/video) | video editing |
51
+ | [Analytics](/templates/analytics) | Amplitude, Mixpanel, Looker |
52
+ | [Forms](/docs/template-forms) | Typeform |
53
+ | [Dispatch](/docs/template-dispatch) | Workspace control plane — secrets, routing, jobs |
54
+ | [Starter](/docs/template-starter) | Minimal scaffold — build from scratch |
52
55
 
53
- Browse the [template gallery](/templates) for live demos and detailed feature lists.
56
+ Browse the [template gallery](/templates) for live demos, or see [Cloneable SaaS](/docs/cloneable-saas) for the full list and the clone → customize → deploy flow.
54
57
 
55
58
  ## Project Structure {#project-structure}
56
59
 
@@ -81,17 +84,29 @@ export default defineConfig();
81
84
  { "extends": "@agent-native/core/tsconfig.base.json" }
82
85
  ```
83
86
 
84
- ```ts
85
- // tailwind.config.ts
86
- import type { Config } from "tailwindcss";
87
- import preset from "@agent-native/core/tailwind";
88
-
89
- export default {
90
- presets: [preset],
91
- content: ["./app/**/*.{ts,tsx}"],
92
- } satisfies Config;
87
+ ```css
88
+ /* app/global.css — Tailwind v4 (CSS-first, no tailwind.config.ts needed) */
89
+ @import "tailwindcss";
90
+ @import "@agent-native/core/styles/agent-native.css";
91
+
92
+ @source "./**/*.{ts,tsx}";
93
+
94
+ :root {
95
+ --background: 0 0% 100%;
96
+ --foreground: 220 10% 10%;
97
+ /* ...rest of your shadcn-style tokens */
98
+ }
99
+
100
+ .dark {
101
+ --background: 220 6% 6%;
102
+ --foreground: 0 0% 90%;
103
+ /* ... */
104
+ }
93
105
  ```
94
106
 
107
+ The framework auto-injects `@tailwindcss/vite` from `defineConfig()`.
108
+ No `tailwind.config.ts`, `postcss.config.js`, or vite changes needed.
109
+
95
110
  ## Architecture Principles {#architecture-principles}
96
111
 
97
112
  These principles apply to all agent-native apps. Understanding them helps you customize templates or build from scratch:
@@ -63,7 +63,7 @@ Subscribe to the `message.im` bot event (and optionally `app_mention` for channe
63
63
 
64
64
  ### 3. Set environment variables
65
65
 
66
- ```
66
+ ```bash
67
67
  SLACK_BOT_TOKEN=xoxb-your-bot-token
68
68
  SLACK_SIGNING_SECRET=your-signing-secret
69
69
  ```
@@ -78,7 +78,7 @@ Message [@BotFather](https://t.me/BotFather) on Telegram and use the `/newbot` c
78
78
 
79
79
  ### 2. Set environment variables
80
80
 
81
- ```
81
+ ```bash
82
82
  TELEGRAM_BOT_TOKEN=your-bot-token
83
83
  ```
84
84
 
@@ -104,7 +104,7 @@ Go to the [Meta Developer Portal](https://developers.facebook.com/), create an a
104
104
 
105
105
  ### 2. Set environment variables
106
106
 
107
- ```
107
+ ```bash
108
108
  WHATSAPP_ACCESS_TOKEN=your-access-token
109
109
  WHATSAPP_VERIFY_TOKEN=your-verify-token
110
110
  WHATSAPP_PHONE_NUMBER_ID=your-phone-number-id
@@ -41,6 +41,23 @@ Six rules govern the architecture:
41
41
  5. **The agent can modify code** — the app evolves as you use it
42
42
  6. **Application state in SQL** — ephemeral UI state lives in the database, readable by both agent and UI
43
43
 
44
+ ## What you get for free {#what-you-get-for-free}
45
+
46
+ Adopting the framework is valuable mostly because of what you stop having to build. The moment your app follows the six rules, you inherit:
47
+
48
+ - **One action = four surfaces.** Every action defined with `defineAction()` is simultaneously an agent tool, a typesafe frontend mutation (`useActionMutation("name")`), an HTTP endpoint at `/_agent-native/actions/:name`, and an MCP tool (when MCP is enabled). External agents can call it over [A2A](/docs/a2a-protocol) too. One implementation, four consumers.
49
+ - **A full workspace per user.** Skills, memory (`learnings.md`), `AGENTS.md`, custom sub-agents, scheduled jobs, connected MCP servers — all SQL-backed, per-user, no dev-box required. See [Workspace](/docs/workspace).
50
+ - **Drop-in React components.** `<AgentPanel />` and `<AgentSidebar />` render chat + workspace anywhere in your app. See [Drop-in Agent](/docs/drop-in-agent).
51
+ - **Live sync between agent and UI.** A 2-second poll invalidates React Query caches whenever the agent writes to the DB. No WebSockets, no serverless-unfriendly long-lived connections. See [Polling Sync](#polling-sync) below.
52
+ - **Auth, orgs, RBAC.** Better Auth with orgs/members/roles is wired in for every template. See [Authentication](/docs/authentication).
53
+ - **Context awareness.** The agent always knows what the user is looking at through the `navigation` app-state key. See [Context Awareness](/docs/context-awareness).
54
+ - **MCP client + server, both directions.** The app ingests MCP servers (local, remote, hub-shared) _and_ exposes its own actions as an MCP server. See [MCP Clients](/docs/mcp-clients) and [MCP Protocol](/docs/mcp-protocol).
55
+ - **Inter-app delegation.** Agents in different apps talk over [A2A](/docs/a2a-protocol). Same-origin deploys skip JWT; cross-origin uses a shared `A2A_SECRET`.
56
+ - **Sub-agent teams.** Spawn a sub-agent with its own thread and tools, surfaced as a chip inline in chat. See [Agent Teams](/docs/agent-teams).
57
+ - **Portability.** Any Drizzle-supported SQL database, any Nitro-compatible host (Node, Workers, Netlify, Vercel, Deno, Lambda, Bun).
58
+
59
+ That's the "and everything else" you'd otherwise be gluing together yourself.
60
+
44
61
  ## The four-area checklist {#four-area-checklist}
45
62
 
46
63
  Every new feature must update all four areas. Skipping any one breaks the agent-native contract.
@@ -65,7 +82,7 @@ Core SQL stores are auto-created and available in every template:
65
82
  - `oauth_tokens` — OAuth credentials
66
83
  - `sessions` — auth sessions
67
84
 
68
- ```bash
85
+ ```ts
69
86
  // Drizzle schema for domain data
70
87
  import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
71
88
 
@@ -76,9 +93,11 @@ export const forms = sqliteTable("forms", {
76
93
  ownerEmail: text("owner_email"),
77
94
  createdAt: integer("created_at").notNull(),
78
95
  });
96
+ ```
79
97
 
80
- // Core actions for quick database access
81
- pnpm action db-schema # show all tables
98
+ ```bash
99
+ # Core actions for quick database access
100
+ pnpm action db-schema # show all tables
82
101
  pnpm action db-query --sql "SELECT * FROM forms"
83
102
  pnpm action db-exec --sql "INSERT INTO forms ..."
84
103
  # Surgical find/replace on a large text column — sends a diff, not the whole value
@@ -110,26 +129,34 @@ Why not call an LLM inline?
110
129
 
111
130
  ## Actions system {#actions-system}
112
131
 
113
- When the agent needs to do something complex — call an API, process data, query the database — it runs an action. Actions are TypeScript files in `actions/` that export a default async function:
132
+ When the agent needs to do something complex — call an API, process data, query the database — it runs an **action**. Actions are TypeScript files in `actions/` that export a default `defineAction()`:
114
133
 
115
134
  ```ts
116
135
  // actions/fetch-data.ts
117
- import { parseArgs } from "@agent-native/core";
118
-
119
- export default async function fetchData(args: string[]) {
120
- const { source } = parseArgs(args);
121
- const res = await fetch(`https://api.example.com/${source}`);
122
- const data = await res.json();
123
- console.log(JSON.stringify(data, null, 2));
124
- }
136
+ import { defineAction } from "@agent-native/core";
137
+ import { z } from "zod";
138
+
139
+ export default defineAction({
140
+ description: "Fetch data from a source API.",
141
+ schema: z.object({
142
+ source: z.string().describe("Data source key, e.g. 'signups'"),
143
+ }),
144
+ run: async ({ source }) => {
145
+ const res = await fetch(`https://api.example.com/${source}`);
146
+ return await res.json();
147
+ },
148
+ });
125
149
  ```
126
150
 
127
- ```bash
128
- # Agent runs actions via CLI
129
- pnpm action fetch-data --source=signups
130
- ```
151
+ One `defineAction()` call gives you:
152
+
153
+ - **Agent tool** — the agent sees it with the zod-derived JSON Schema and can call it.
154
+ - **Frontend mutation** — `useActionMutation("fetch-data")` with full TypeScript inference.
155
+ - **HTTP endpoint** — `POST /_agent-native/actions/fetch-data` (auto-mounted).
156
+ - **CLI** — `pnpm action fetch-data --source=signups` for scripting and agent dev loops.
157
+ - **MCP tool / A2A tool** — when MCP server or A2A is enabled, the same action shows up there too.
131
158
 
132
- This means anything the UI can do, the agent can do — and vice versa. The UI calls `POST /api/fetch-data`, the agent calls `pnpm action fetch-data`. Same logic, same results, different entry points.
159
+ Same logic, one definition, wired to every consumer automatically. See [Actions](/docs/actions) for the full reference.
133
160
 
134
161
  ## Polling sync {#polling-sync}
135
162
 
@@ -169,14 +196,14 @@ The agent always knows what the user is looking at. The UI writes a `navigation`
169
196
 
170
197
  See [Context Awareness](/docs/context-awareness) for the full pattern: navigation state, view-screen, navigate commands, and jitter prevention.
171
198
 
172
- ## APIs & CLIs, not MCPs {#apis-and-clis}
199
+ ## Actions, MCP, and A2A — one surface, many protocols {#protocols}
173
200
 
174
- Agent-native apps can work with MCP servers, but the architecture leans heavily on something more standard: **regular APIs and CLIs accessed through code execution**. Agents are great at writing code that calls `fetch()` or runs a CLI command — no special protocol needed.
201
+ Every action you define automatically becomes available over multiple protocols you don't pick one. The framework runs both an MCP server and an A2A peer for your app, with actions feeding both.
175
202
 
176
- - **No wrapper layer.** Call APIs directly with `fetch()` or use official SDKs.
177
- - **Any CLI works.** `ffmpeg`, `gh`, `aws`, `gcloud`if it runs in a terminal, the agent can use it.
178
- - **Code is the protocol.** TypeScript actions are more expressive than any tool schema.
179
- - **MCP is additive.** Use MCP servers alongside actions if you want, but they're not required.
203
+ - **Actions first.** Write the logic once as an action. Use `fetch()` and any SDK you want inside — no wrapper layer.
204
+ - **MCP for the outside world.** Your actions show up as MCP tools to Claude Desktop, ChatGPT's remote-MCP support, and any other MCP client. Your app also _consumes_ MCP servers local, remote, or from a workspace hub. See [MCP Clients](/docs/mcp-clients) and [MCP Protocol](/docs/mcp-protocol).
205
+ - **A2A for other agents.** Other agent-native apps discover and call your actions over [A2A](/docs/a2a-protocol) same-origin deploys skip JWT entirely.
206
+ - **CLIs still work.** `pnpm action <name>` and direct shell tools (`ffmpeg`, `gh`, `aws`) remain available whenever they're the simplest path.
180
207
 
181
208
  ## Agent modifies code {#agent-modifies-code}
182
209
 
@@ -9,6 +9,8 @@ Agent-native apps can also act as MCP **clients** — connecting to locally inst
9
9
 
10
10
  With one config file, every agent-native app in your workspace gains access to tools provided by MCP servers on your machine: `claude-in-chrome` for browser automation, `@modelcontextprotocol/server-filesystem` for reading files, `@modelcontextprotocol/server-playwright` for browser testing, and anything else that speaks MCP.
11
11
 
12
+ You can also [connect remote (HTTP) MCP servers at runtime](#remote-via-ui) — individual users or whole organizations — without editing a config file.
13
+
12
14
  ## Adding a local MCP server {#adding-a-server}
13
15
 
14
16
  Create `mcp.config.json` at your workspace root (or at an individual app root — workspace root wins when both exist):
@@ -73,6 +75,75 @@ If you have **no** `mcp.config.json` and the `claude-in-chrome-mcp` binary is on
73
75
 
74
76
  This means users who've installed the claude-in-chrome extension get browser control across every agent-native app they open with no config changes.
75
77
 
78
+ ## Remote MCP servers via the settings UI {#remote-via-ui}
79
+
80
+ Users don't have to edit `mcp.config.json` to add a remote, HTTP-based MCP server (Zapier, Cloudflare, Composio, an internal tool, etc). Open the settings panel → **MCP Servers** and paste the server's URL. Two scopes are supported:
81
+
82
+ - **Personal** — only the signed-in user gets the tools. Stored as a user-scope setting.
83
+ - **Team** — everyone in the active organization gets the tools. Owners and admins can add; members see the list read-only. Stored as an org-scope setting.
84
+
85
+ Adds and removes hot-reload into the running MCP manager — no process restart, and no server restart. The new `mcp__<scope>-<name>__*` tools appear to the agent on the next message.
86
+
87
+ HTTPS URLs are accepted everywhere; plain `http://` is only allowed for `localhost` during development. Optional auth goes in as a Bearer token that's sent via `Authorization: Bearer …` on every request.
88
+
89
+ Under the hood these servers are persisted in the framework's `settings` table under the key `u:<email>:mcp-servers-remote` (Personal) or `o:<orgId>:mcp-servers-remote` (Team) and merged with `mcp.config.json` on startup.
90
+
91
+ ### HTTP endpoints
92
+
93
+ | Method | Route | Purpose |
94
+ | ------ | ----------------------------------------------------- | ---------------------------------------------------------------------- |
95
+ | GET | `/_agent-native/mcp/servers` | List the current user's personal + org servers with live status. |
96
+ | POST | `/_agent-native/mcp/servers` | Add a server. Body: `{ scope, name, url, headers?, description? }`. |
97
+ | DELETE | `/_agent-native/mcp/servers/:id?scope=user\|org` | Remove a server and reconfigure the manager. |
98
+ | POST | `/_agent-native/mcp/servers/:id/test?scope=user\|org` | Dry-run the existing server's connect + list-tools. |
99
+ | POST | `/_agent-native/mcp/servers/test` | Dry-run an arbitrary URL before persisting. Body: `{ url, headers? }`. |
100
+
101
+ Stdio servers are still a no-op outside Node runtimes, but remote HTTP MCP servers work in any environment with `fetch` — including desktop production builds.
102
+
103
+ ## Shared MCP servers via a hub {#hub}
104
+
105
+ If your workspace runs multiple agent-native apps (e.g. dispatch + mail + clips), you can configure **one** app as the hub and have the others pull its org-scope MCP servers automatically. No per-app copy-paste of URLs and bearer tokens.
106
+
107
+ Dispatch is the conventional hub — it already coordinates across apps.
108
+
109
+ ### 1. Enable hub-serve on the hub app (dispatch)
110
+
111
+ Set an env var in dispatch's deployment:
112
+
113
+ ```bash
114
+ AGENT_NATIVE_MCP_HUB_TOKEN=<a-long-random-secret>
115
+ ```
116
+
117
+ Dispatch now mounts `GET /_agent-native/mcp/hub/servers` which returns every org-scope MCP server stored in its `settings` table, with full URL + headers, authenticated by the token.
118
+
119
+ ### 2. Point consuming apps at the hub
120
+
121
+ Set on every consumer (mail, clips, whatever):
122
+
123
+ ```bash
124
+ AGENT_NATIVE_MCP_HUB_URL=https://dispatch.acme.com
125
+ AGENT_NATIVE_MCP_HUB_TOKEN=<the-same-secret>
126
+ ```
127
+
128
+ At startup, each consumer pulls the hub's server list and merges it into its own MCP manager. The tools appear to the agent as `mcp__hub_<orgId>_<name>__*` — distinct from the consumer's own local `mcp__org_…` so there's no collision.
129
+
130
+ ### 3. What gets shared
131
+
132
+ Only **org-scope** servers are shared. User-scope (Personal) servers stay with the user who added them — the hub never re-exposes personal credentials across apps.
133
+
134
+ Hub responses include the full auth headers (Bearer tokens etc). The transport is HTTPS, the endpoint requires the shared secret, and it only returns org-scope rows — treat the hub URL + token like a database credential.
135
+
136
+ ### 4. Hot reload vs restart
137
+
138
+ Local UI adds in each app hot-reload via `McpClientManager.reconfigure()` — no restart. Hub-sourced servers currently re-fetch only when a local mutation triggers a reconfigure (or when the app restarts), so if you add a new server in dispatch, other apps pick it up on their next restart or next local change. Periodic background refresh is on the roadmap.
139
+
140
+ ### Endpoints summary
141
+
142
+ | Method | Route | Purpose |
143
+ | ------ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
144
+ | GET | `/_agent-native/mcp/hub/servers` | Serve all org-scope servers with full creds (bearer-gated, only mounted when `AGENT_NATIVE_MCP_HUB_TOKEN` is set). |
145
+ | GET | `/_agent-native/mcp/hub/status` | Returns `{ serving, consuming, hubUrl }` for the settings UI card. |
146
+
76
147
  ## Status route {#status-route}
77
148
 
78
149
  Every app exposes `GET /_agent-native/mcp/status` for tooling and onboarding:
@@ -0,0 +1,69 @@
1
+ ---
2
+ title: "Pure-Agent Apps"
3
+ description: "Build an agent without a heavy UI — just the agent plus a minimal observability/management surface. All the framework benefits, none of the dashboard work."
4
+ ---
5
+
6
+ # Pure-Agent Apps
7
+
8
+ Not every agent-native app needs a full SaaS-style interface. Sometimes the agent _is_ the product. A support triage agent. A daily report generator. A research bot. An email auto-responder. An ops runbook executor.
9
+
10
+ For these, the "app" is mostly just the agent doing work in the background. You still want a UI — but a minimal one, focused on **observability, management, and steering** rather than hand-crafted dashboards and forms.
11
+
12
+ This is the "agents benefit from a UI even when there's no rich app around them" pattern. The hot take is "agents will replace apps." The reality is "every agent eventually needs a UI for humans to supervise, configure, and debug it." Agent-native gives you that UI for free.
13
+
14
+ ## The minimum viable UI {#minimum-ui}
15
+
16
+ A pure-agent app ships with five surfaces, all provided by the framework — you don't build them:
17
+
18
+ 1. **Chat** — the main input. Users talk to the agent, steer it, queue tasks. (`<AgentSidebar>` or `<AgentPanel>`)
19
+ 2. **Workspace** — skills, memory (`learnings.md`), `AGENTS.md`, custom sub-agents, connected MCP servers, scheduled jobs. Customize the agent's behavior without shipping code. (Workspace tab in the sidebar)
20
+ 3. **Job history** — which scheduled jobs ran, when, whether they succeeded, what they did. (Workspace tab → `jobs/`)
21
+ 4. **Thread history** — every past conversation, each preserved with its tool calls and final output. (Chat tab)
22
+ 5. **Settings** — API keys, connected accounts, onboarding status. (Sidebar settings)
23
+
24
+ Those five together are enough UI for most pure-agent use cases. No analytics dashboard. No Kanban. No forms. Just: talk to it, see what it's done, configure how it behaves.
25
+
26
+ ## When to pick this pattern {#when-to-pick}
27
+
28
+ Pure-agent makes sense when:
29
+
30
+ - **The work happens in the background.** Scheduled jobs, webhook-triggered handlers, Slack/Telegram responders. Users rarely sit in the app.
31
+ - **The output leaves the app.** The agent posts to Slack, sends email, writes to a third-party system. There's nothing to view in-app; the value is elsewhere.
32
+ - **The domain is one-shot.** A research bot that returns a report. No persistent object to dashboard.
33
+ - **You're prototyping.** Ship the agent now; add a rich UI only when you've proven users need it.
34
+
35
+ Pick a full [cloneable SaaS](/docs/cloneable-saas) template instead when the app has real persistent objects (emails, events, documents, charts) users need to browse, pivot, and share.
36
+
37
+ ## The minimal scaffold {#scaffold}
38
+
39
+ Start from the **Starter** template:
40
+
41
+ ```bash
42
+ pnpm dlx @agent-native/core create my-agent --template starter
43
+ ```
44
+
45
+ Starter gives you the six-rules architecture, the agent panel, the workspace, auth, polling, and one example action — and nothing else. Add your own actions in `actions/`, connect any MCP servers you need, write the relevant skills into the workspace, and you're done. The "UI" is the agent sidebar — which is already complete.
46
+
47
+ If you really want _zero_ UI except the agent, `app/routes/index.tsx` can just render `<AgentPanel defaultMode="chat" />` fullscreen. The only thing the user sees is the chat. Everything else — job history, workspace, settings — is one click away in the panel's tabs.
48
+
49
+ ## What you still get for free {#still-free}
50
+
51
+ Even with no custom UI, you still inherit every framework benefit:
52
+
53
+ - **Actions** as agent tools + HTTP endpoints + MCP tools + A2A tools. External agents, Claude Desktop, and your own HTTP clients can drive the agent without going through the chat UI.
54
+ - **Recurring jobs** for scheduled work — "every morning at 7 summarize my unread emails and post to Slack."
55
+ - **The workspace** for per-user customization, skills, memory, MCP connections.
56
+ - **Sub-agent delegation** via [agent teams](/docs/agent-teams).
57
+ - **Portability** — deploys to any serverless host, any SQL database.
58
+ - **Multi-tenant by default** — each user gets their own workspace without a dev-box.
59
+
60
+ ## Adding a tiny bit of UI {#tiny-ui}
61
+
62
+ Most "pure-agent" apps eventually want a little bit of custom UI — not a dashboard, but maybe a status page, a job history, or a config screen. The [drop-in agent](/docs/drop-in-agent) components coexist with anything else you render. Add a single `/status` route that lists recent runs; keep everything else in the chat. That's usually enough.
63
+
64
+ ## What's next
65
+
66
+ - [**Recurring Jobs**](/docs/recurring-jobs) — scheduled prompts the agent runs on its own
67
+ - [**Drop-in Agent**](/docs/drop-in-agent) — mounting `<AgentPanel>` fullscreen or in a sidebar
68
+ - [**Actions**](/docs/actions) — the tools your pure-agent will call
69
+ - [**Workspace**](/docs/workspace) — the customization surface for skills, memory, and MCP servers