@agent-native/core 0.157.3 → 0.157.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +40 -1
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +3 -1
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +7 -7
- package/corpus/templates/clips/actions/approve-recording-access-request.ts +147 -0
- package/corpus/templates/clips/actions/request-recording-access.ts +121 -23
- package/corpus/templates/clips/actions/view-screen.ts +1 -1
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +34 -53
- package/corpus/templates/clips/app/components/player/request-access-dialog.tsx +104 -0
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +36 -45
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +3 -6
- package/corpus/templates/clips/app/i18n/en-US.ts +26 -1
- package/corpus/templates/clips/app/lib/public-meeting.ts +1 -1
- package/corpus/templates/clips/app/routes/access-request.approve.tsx +250 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +9 -32
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +123 -37
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +41 -1
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +1 -0
- package/corpus/templates/clips/server/lib/emails.ts +40 -11
- package/corpus/templates/clips/shared/recording-link.ts +32 -1
- package/corpus/templates/clips/shared/share-attribution.ts +13 -0
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/content/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +22 -10
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +2 -1
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +245 -9
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +185 -134
- package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +61 -45
- package/corpus/templates/content/app/components/editor/extensions/ImageNode.ts +6 -0
- package/corpus/templates/content/app/components/editor/image-upload.ts +137 -5
- package/corpus/templates/content/app/global.css +8 -0
- package/corpus/templates/content/changelog/2026-08-12-image-uploads-now-confirm-the-image-can-be-displayed-before-.md +6 -0
- package/corpus/templates/content/changelog/2026-08-14-images-fill-the-page-width-by-default-and-remain-visible-whe.md +6 -0
- package/corpus/templates/content/changelog/2026-08-14-images-inserted-from-the-slash-command-stay-saved-after-uplo.md +6 -0
- package/corpus/templates/content/changelog/2026-08-14-svg-files-can-be-selected-reliably-from-the-image-picker.md +6 -0
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/design/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -1
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +25 -30
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +2 -1
- package/corpus/templates/slides/app/components/editor/ShareDialog.tsx +124 -180
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +1 -0
- package/corpus/templates/slides/app/global.css +99 -3
- package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +21 -0
- package/dist/chat-threads/schema.d.ts +1 -1
- package/dist/cli/code-agent-executor.js +318 -0
- package/dist/client/AgentPanel.d.ts +13 -1
- package/dist/client/AgentPanel.js +41 -3
- package/dist/client/AssistantChat.d.ts +9 -1
- package/dist/client/AssistantChat.js +26 -13
- package/dist/client/MultiTabAssistantChat.js +18 -5
- package/dist/client/agent-chat.d.ts +8 -0
- package/dist/client/agent-chat.js +15 -0
- package/dist/client/app-chat-sidebar.d.ts +23 -0
- package/dist/client/app-chat-sidebar.js +53 -0
- package/dist/client/app-providers.js +31 -2
- package/dist/client/frame-protocol.d.ts +20 -2
- package/dist/client/hooks/index.d.ts +1 -0
- package/dist/client/hooks/index.js +1 -0
- package/dist/client/sharing/AgentShareSection.d.ts +8 -0
- package/dist/client/sharing/AgentShareSection.js +50 -0
- package/dist/client/sharing/ShareButton.js +2 -1
- package/dist/client/sharing/ShareDialog.d.ts +2 -2
- package/dist/client/sharing/ShareDialog.js +21 -29
- package/dist/client/sharing/index.d.ts +1 -0
- package/dist/client/sharing/index.js +1 -0
- package/dist/client/sharing/useShareButtonController.d.ts +1 -0
- package/dist/client/sharing/useShareDialogController.d.ts +3 -0
- package/dist/client/sharing/useShareDialogController.js +2 -1
- package/dist/client/theme.d.ts +21 -0
- package/dist/client/theme.js +60 -0
- package/dist/client/ui/index.d.ts +1 -1
- package/dist/client/ui/index.js +1 -1
- package/dist/client/use-session.js +23 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/dashboard-storage/schema.d.ts +1 -1
- package/dist/data-programs/schema.d.ts +1 -1
- package/dist/extensions/schema.d.ts +1 -1
- package/dist/localization/core-messages/ar-SA.js +6 -0
- package/dist/localization/core-messages/de-DE.js +6 -0
- package/dist/localization/core-messages/en-US.d.ts +6 -0
- package/dist/localization/core-messages/en-US.js +6 -0
- package/dist/localization/core-messages/es-ES.js +6 -0
- package/dist/localization/core-messages/fr-FR.js +6 -0
- package/dist/localization/core-messages/hi-IN.js +6 -0
- package/dist/localization/core-messages/ja-JP.js +6 -0
- package/dist/localization/core-messages/ko-KR.js +6 -0
- package/dist/localization/core-messages/pt-BR.js +6 -0
- package/dist/localization/core-messages/zh-CN.js +6 -0
- package/dist/localization/core-messages/zh-TW.js +6 -0
- package/dist/localization/core-messages.d.ts +6 -0
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.js +1 -0
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +14 -14
- package/dist/server/auth.js +8 -5
- package/dist/server/identity-sso-store.d.ts +6 -1
- package/dist/server/identity-sso-store.js +57 -14
- package/dist/server/identity-sso.d.ts +7 -8
- package/dist/server/identity-sso.js +15 -12
- package/dist/sharing/actions/list-resource-shares.d.ts +2 -0
- package/dist/sharing/actions/list-resource-shares.js +1 -0
- package/dist/sharing/schema.d.ts +1 -1
- package/dist/sharing/schema.js +4 -1
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/sharing/SKILL.md +21 -0
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +21 -0
- package/docs/content/actions-access-control.mdx +226 -0
- package/docs/content/actions-advanced.mdx +152 -0
- package/docs/content/actions-defining.mdx +275 -0
- package/docs/content/actions-other-surfaces.mdx +167 -0
- package/docs/content/actions-overview.mdx +214 -0
- package/docs/content/actions-run-context.mdx +180 -0
- package/docs/content/agent-surfaces.mdx +1 -1
- package/docs/content/agent-teams.mdx +1 -1
- package/docs/content/agent-web-surfaces.mdx +1 -1
- package/docs/content/audit-log.mdx +1 -1
- package/docs/content/automation-connectors.mdx +1 -1
- package/docs/content/automations.mdx +1 -1
- package/docs/content/blueprint-installer.mdx +1 -1
- package/docs/content/cli-adapters.mdx +1 -1
- package/docs/content/client-agent-chat.mdx +1 -1
- package/docs/content/client-data.mdx +2 -2
- package/docs/content/client-overview.mdx +2 -2
- package/docs/content/components.mdx +1 -1
- package/docs/content/cross-app-sso.mdx +24 -17
- package/docs/content/data-programs.mdx +2 -2
- package/docs/content/database.mdx +1 -1
- package/docs/content/deployment.mdx +1 -1
- package/docs/content/docs-components.mdx +14 -3
- package/docs/content/drop-in-agent.mdx +2 -2
- package/docs/content/durable-resume.mdx +1 -1
- package/docs/content/evals.mdx +1 -1
- package/docs/content/extensions.mdx +1 -1
- package/docs/content/external-agents-catalog.mdx +2 -2
- package/docs/content/external-agents.mdx +1 -1
- package/docs/content/generative-ui.mdx +1 -1
- package/docs/content/getting-started.mdx +1 -1
- package/docs/content/http-api.mdx +4 -4
- package/docs/content/human-approval.mdx +1 -1
- package/docs/content/key-concepts.mdx +1 -1
- package/docs/content/mcp-apps.mdx +1 -1
- package/docs/content/mcp-clients.mdx +1 -1
- package/docs/content/mcp-protocol.mdx +1 -1
- package/docs/content/native-chat-ui.mdx +1 -1
- package/docs/content/observability.mdx +1 -1
- package/docs/content/organizations-teams-permissions.mdx +1 -1
- package/docs/content/processors.mdx +1 -1
- package/docs/content/pure-agent-apps.mdx +1 -1
- package/docs/content/recurring-jobs.mdx +1 -1
- package/docs/content/server-database.mdx +1 -1
- package/docs/content/server-overview.mdx +3 -3
- package/docs/content/server-routes.mdx +2 -2
- package/docs/content/template-analytics-developers.mdx +1 -1
- package/docs/content/template-assets-developers.mdx +1 -1
- package/docs/content/template-brain-developers.mdx +1 -1
- package/docs/content/template-calendar-developers.mdx +1 -1
- package/docs/content/template-chat-first-edits.mdx +1 -1
- package/docs/content/template-chat.mdx +1 -1
- package/docs/content/template-content-developers.mdx +1 -1
- package/docs/content/template-forms-developers.mdx +1 -1
- package/docs/content/template-forms.mdx +1 -1
- package/docs/content/template-mail-developers.mdx +2 -2
- package/docs/content/toolkit-org-team.mdx +1 -1
- package/docs/content/tracking.mdx +1 -1
- package/docs/content/what-is-agent-native.mdx +1 -1
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/sharing/SKILL.md +21 -0
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +21 -0
- package/docs/content/actions.mdx +0 -750
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Overview"
|
|
3
|
+
description: "Actions are the single source of truth for anything your app does. Define one with defineAction() and it fans out to an agent tool, UI hooks, HTTP, an MCP tool, an A2A tool, and a CLI command."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Overview
|
|
7
|
+
|
|
8
|
+
Actions are the single source of truth for anything your app does. Define one with `defineAction()` and drop it in `actions/`. Every surface below picks it up automatically. You write the logic once. No surface gets its own copy, and none can drift out of sync with the others.
|
|
9
|
+
|
|
10
|
+
<Cards columns={2}>
|
|
11
|
+
|
|
12
|
+
### :robot: [Agent Tool](/docs/agent-surfaces)
|
|
13
|
+
|
|
14
|
+
The agent reads the description and schema as a callable tool. Ask for it in chat, like "reply to this ticket" or "summarize this thread."
|
|
15
|
+
|
|
16
|
+
### :components: [UI Hooks](/docs/client-data)
|
|
17
|
+
|
|
18
|
+
`useActionQuery()`, `useActionMutation()`, and `callAction()` call the same action from React. A click and a chat message run the exact same operation.
|
|
19
|
+
|
|
20
|
+
### :server: [Framework Transport](/docs/http-api)
|
|
21
|
+
|
|
22
|
+
Auto-mounted at `/_agent-native/actions/<name>` on startup. The UI hooks call this route under the hood, and an external HTTP client can call it directly too.
|
|
23
|
+
|
|
24
|
+
### :plug: [MCP Tool](/docs/actions-other-surfaces#mcp)
|
|
25
|
+
|
|
26
|
+
Shows up as a tool to any MCP host: Claude, Claude Desktop, Cursor, Codex. Use it when a different AI client should drive your app.
|
|
27
|
+
|
|
28
|
+
### :network: [A2A Tool](/docs/actions-other-surfaces#a2a)
|
|
29
|
+
|
|
30
|
+
Other agent-native apps discover and call it over A2A. Use it when a second app in your workspace needs this one to act on its behalf.
|
|
31
|
+
|
|
32
|
+
### :terminal: [CLI Command](/docs/actions-other-surfaces#cli)
|
|
33
|
+
|
|
34
|
+
`pnpm action <name>` runs it from a terminal. Use it for scripts, cron jobs, and quick manual tests.
|
|
35
|
+
|
|
36
|
+
</Cards>
|
|
37
|
+
|
|
38
|
+
Most apps build a separate API layer between the frontend and the database, one that only the browser can call. An agent that wants the same capability needs its own, separate integration, written and maintained again. Agent-native apps skip that split. The UI and the agent call the exact same action, so there is only one implementation to write, and only one place for a bug to hide.
|
|
39
|
+
|
|
40
|
+
<Diagram id="doc-block-actions-overview-2" title="Traditional frontend vs. Agent Native" summary="A traditional frontend calls its own API layer, which only it can reach. In Agent Native, app/ and the agent both call the same actions, so every capability built here is agent-callable for free.">
|
|
41
|
+
|
|
42
|
+
```html
|
|
43
|
+
<div class="diagram-cocmp">
|
|
44
|
+
<div class="cocmp-col">
|
|
45
|
+
<div class="cocmp-label diagram-muted">Traditional</div>
|
|
46
|
+
<div class="diagram-node">app/ (React frontend)</div>
|
|
47
|
+
<div class="cocmp-arrow diagram-muted" aria-hidden="true">↓</div>
|
|
48
|
+
<div class="diagram-panel" data-rough>
|
|
49
|
+
<strong>API layer</strong>
|
|
50
|
+
<small class="diagram-muted">only the frontend calls it</small>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="cocmp-arrow diagram-muted" aria-hidden="true">↓</div>
|
|
53
|
+
<div class="diagram-box" data-rough>Database</div>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="cocmp-vs diagram-muted">vs</div>
|
|
56
|
+
<div class="cocmp-col">
|
|
57
|
+
<div class="cocmp-label diagram-muted">Agent Native</div>
|
|
58
|
+
<div class="cocmp-callers">
|
|
59
|
+
<div class="diagram-node">app/ (React frontend)</div>
|
|
60
|
+
<div class="diagram-node">Agent</div>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="cocmp-arrow diagram-muted" aria-hidden="true">↓</div>
|
|
63
|
+
<div class="diagram-panel" data-rough>
|
|
64
|
+
<span class="diagram-pill accent">Actions</span
|
|
65
|
+
><small class="diagram-muted">equal partners, same operations</small>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="cocmp-arrow diagram-muted" aria-hidden="true">↓</div>
|
|
68
|
+
<div class="diagram-box" data-rough>SQL database</div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```css
|
|
74
|
+
.diagram-cocmp {
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: flex-start;
|
|
77
|
+
gap: 28px;
|
|
78
|
+
flex-wrap: wrap;
|
|
79
|
+
}
|
|
80
|
+
.cocmp-col {
|
|
81
|
+
display: flex;
|
|
82
|
+
flex-direction: column;
|
|
83
|
+
align-items: center;
|
|
84
|
+
gap: 8px;
|
|
85
|
+
flex: 1;
|
|
86
|
+
min-width: 180px;
|
|
87
|
+
}
|
|
88
|
+
.cocmp-label {
|
|
89
|
+
font-size: 11px;
|
|
90
|
+
text-transform: uppercase;
|
|
91
|
+
letter-spacing: 0.06em;
|
|
92
|
+
font-weight: 600;
|
|
93
|
+
}
|
|
94
|
+
.cocmp-callers {
|
|
95
|
+
display: flex;
|
|
96
|
+
gap: 8px;
|
|
97
|
+
flex-wrap: wrap;
|
|
98
|
+
justify-content: center;
|
|
99
|
+
}
|
|
100
|
+
.cocmp-vs {
|
|
101
|
+
font-size: 13px;
|
|
102
|
+
font-weight: 600;
|
|
103
|
+
padding-top: 52px;
|
|
104
|
+
}
|
|
105
|
+
.diagram-cocmp .diagram-panel {
|
|
106
|
+
display: flex;
|
|
107
|
+
flex-direction: column;
|
|
108
|
+
gap: 6px;
|
|
109
|
+
padding: 12px 16px;
|
|
110
|
+
align-self: stretch;
|
|
111
|
+
align-items: center;
|
|
112
|
+
}
|
|
113
|
+
.cocmp-arrow {
|
|
114
|
+
font-size: 18px;
|
|
115
|
+
line-height: 1;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
</Diagram>
|
|
120
|
+
|
|
121
|
+
If the UI and the agent both need to do something, reach for an action instead of a custom route. For the rare case where a route-shaped protocol is the right call, visit [Prefer Actions For App Operations](/docs/server-overview#actions-first).
|
|
122
|
+
|
|
123
|
+
## Where Actions Fit {#role}
|
|
124
|
+
|
|
125
|
+
`app/` (visit [Client Overview](/docs/client-overview#role)) and the agent both resolve to the same actions and the same SQL database. There is no separate "app backend" this layer talks to that the agent can't also reach. Building a feature means defining an operation here and getting a UI, an agent tool, and every other surface for it at the same time.
|
|
126
|
+
|
|
127
|
+
`actions/` itself is a flat folder. Each file is one action: a `defineAction()` call exported as the file's default export. The framework scans this folder on startup and mounts every file it finds. There is no registration step and no index file to keep up to date.
|
|
128
|
+
|
|
129
|
+
An action's `run()` body is regular server code, so it commonly reaches into a few other directories:
|
|
130
|
+
|
|
131
|
+
<FileTree
|
|
132
|
+
id="doc-block-actions-overview-filetree"
|
|
133
|
+
entries={[
|
|
134
|
+
{
|
|
135
|
+
path: "actions/reply-to-email.ts",
|
|
136
|
+
note: "One action per file. Exports a defineAction() call, and the framework mounts it automatically.",
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
path: "server/db/schema.ts",
|
|
140
|
+
note: "Drizzle table definitions most actions read and write through.",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
path: "server/lib/access.ts",
|
|
144
|
+
note: "Shared access guards (accessFilter, assertAccess, authorize) reused across actions.",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
path: "shared/feature-flags.ts",
|
|
148
|
+
note: "Flag definitions an action and a server plugin both check.",
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
path: "app/components/ReplyButton.tsx",
|
|
152
|
+
note: "Calls the action from the UI with useActionMutation.",
|
|
153
|
+
},
|
|
154
|
+
]}
|
|
155
|
+
/>
|
|
156
|
+
|
|
157
|
+
Nothing outside `actions/` should import an action's `run` function directly. Call it through one of the surfaces above instead: the agent tool, a UI hook, HTTP, MCP, A2A, or the CLI. Every one of those paths runs the same schema validation, access checks, and audit trail.
|
|
158
|
+
|
|
159
|
+
## Start with one action {#hello-action}
|
|
160
|
+
|
|
161
|
+
The first operation in a chat-first app can be tiny. In the Chat template,
|
|
162
|
+
replace `actions/hello.ts` or add a new file beside it:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
// actions/hello.ts
|
|
166
|
+
import { defineAction } from "@agent-native/core/action";
|
|
167
|
+
import { z } from "zod";
|
|
168
|
+
|
|
169
|
+
export default defineAction({
|
|
170
|
+
description: "Say hello from the local agent.",
|
|
171
|
+
schema: z.object({
|
|
172
|
+
name: z.string().default("world"),
|
|
173
|
+
}),
|
|
174
|
+
http: { method: "GET" },
|
|
175
|
+
readOnly: true,
|
|
176
|
+
run: async ({ name }) => {
|
|
177
|
+
return { message: `Hello, ${name}!` };
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Run it from the same folder:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
pnpm action hello '{"name":"Steve"}'
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The CLI accepts a JSON object as the action input, which matches the structured
|
|
189
|
+
tool calls agents already make. Simple flags still work for quick manual runs:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
pnpm action hello --name Steve
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Then run the app-agent loop against the folder:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
npx agent-native agent "Call hello for Steve and explain the result"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
That is the same app-agent loop your scheduled jobs, chat UI, external MCP
|
|
202
|
+
tools, and future screens will use. Chat and domain templates are for adding UI
|
|
203
|
+
around actions, not a required prerequisite for the action itself.
|
|
204
|
+
|
|
205
|
+
## What's next
|
|
206
|
+
|
|
207
|
+
- [**Defining Actions**](/docs/actions-defining) — `defineAction()` anatomy, schema, and HTTP config
|
|
208
|
+
- [**Access & Authorization**](/docs/actions-access-control) — exposure flags, `ctx` scoping, and `authorize`
|
|
209
|
+
- [**Run Context**](/docs/actions-run-context) — the full `ctx` field table
|
|
210
|
+
- [**Other Surfaces**](/docs/actions-other-surfaces) — native chat UI, CLI, A2A, MCP, and standard actions
|
|
211
|
+
- [**Advanced & Legacy**](/docs/actions-advanced) — feature-flag gating and legacy CLI-style actions
|
|
212
|
+
- [**Overview**](/docs/client-overview) — the `app/` side of this same contract
|
|
213
|
+
- [**Data & Sync**](/docs/client-data) — `useActionQuery`, `useActionMutation`, and `callAction` in the UI
|
|
214
|
+
- [**Agent Surfaces**](/docs/agent-surfaces) — how one action grows from chat tool to full screen
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Run Context"
|
|
3
|
+
description: "The ctx second argument passed to run(): the full ActionRunContext signature and the caller union, for tracking, automation attribution, and cross-cutting concerns."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Run Context
|
|
7
|
+
|
|
8
|
+
`run` receives an optional second argument, `ctx`, carrying the resolved request identity and the surface that invoked the action. Read it instead of calling `getRequestUserEmail()` / `getRequestOrgId()` by hand, and pass the whole `ctx` to tracking:
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
export default defineAction({
|
|
12
|
+
description: "Log an audit entry for the current request.",
|
|
13
|
+
schema: z.object({ event: z.string() }),
|
|
14
|
+
run: async (args, ctx) => {
|
|
15
|
+
// ctx is undefined-safe: a 1-arg `run(args)` is still valid.
|
|
16
|
+
const actor = ctx?.userEmail ?? "system";
|
|
17
|
+
if (ctx?.caller === "frontend") {
|
|
18
|
+
// tighter rules for browser-initiated calls, looser for "tool"/"cli"
|
|
19
|
+
}
|
|
20
|
+
await db.insert(audit).values({
|
|
21
|
+
actor,
|
|
22
|
+
orgId: ctx?.orgId ?? null,
|
|
23
|
+
source: ctx?.caller ?? "unknown",
|
|
24
|
+
event: args.event,
|
|
25
|
+
});
|
|
26
|
+
return { ok: true };
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Most actions only ever read `ctx?.userEmail` and `ctx?.orgId`, the [access-control scoping](/docs/actions-access-control#access-control) used in nearly every real action. The rest of this page covers cross-cutting concerns like tracking and automation attribution, which fewer actions need.
|
|
32
|
+
|
|
33
|
+
## The `ctx` argument {#ctx}
|
|
34
|
+
|
|
35
|
+
`ctx` carries two kinds of information: the resolved request identity (`userEmail`, `orgId`) that's present on nearly every call, and metadata about the surface that invoked the action (`caller`, plus surface-specific fields like `threadId` or `automation` that are only populated for certain callers). The full shape, as the second argument to `run()`:
|
|
36
|
+
|
|
37
|
+
<Signature
|
|
38
|
+
id="doc-block-actions-run-context-1"
|
|
39
|
+
name="run"
|
|
40
|
+
params={[
|
|
41
|
+
{
|
|
42
|
+
name: "args",
|
|
43
|
+
type: "TInput",
|
|
44
|
+
description: "The validated input, parsed from `schema`.",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "ctx",
|
|
48
|
+
type: "ActionRunContext",
|
|
49
|
+
optional: true,
|
|
50
|
+
description:
|
|
51
|
+
"The resolved request identity and the surface that invoked the action. Undefined-safe: a 1-argument `run(args)` handler is still valid.",
|
|
52
|
+
fields: [
|
|
53
|
+
{
|
|
54
|
+
name: "userEmail",
|
|
55
|
+
type: "string",
|
|
56
|
+
optional: true,
|
|
57
|
+
description:
|
|
58
|
+
"Resolved request user. **Never defaulted to a dev identity**: `undefined` when the request has no authenticated user. Apply your own fallback if you need one.",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "orgId",
|
|
62
|
+
type: "string | null",
|
|
63
|
+
description:
|
|
64
|
+
"Resolved org id, or `null` when the request has no org.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "caller",
|
|
68
|
+
type: "ActionCaller",
|
|
69
|
+
description:
|
|
70
|
+
"How the action was invoked. See [the caller union](#caller) below.",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "send",
|
|
74
|
+
type: "(event) => void",
|
|
75
|
+
optional: true,
|
|
76
|
+
description:
|
|
77
|
+
'Emits an SSE event to the client. Only present inside the agent tool loop (`caller: "tool"`). `undefined` elsewhere.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "attachments",
|
|
81
|
+
type: "AgentChatAttachment[]",
|
|
82
|
+
optional: true,
|
|
83
|
+
description:
|
|
84
|
+
'Files, images, and pasted text blocks submitted with the current agent turn. Populated only when `caller: "tool"`. `undefined` on all other surfaces.',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "signal",
|
|
88
|
+
type: "AbortSignal",
|
|
89
|
+
optional: true,
|
|
90
|
+
description:
|
|
91
|
+
'Aborts when the run is soft-timed-out, cancelled, or the server shuts down. Populated only when `caller: "tool"`. Long-running actions can observe it to cancel early instead of waiting for the per-tool 60s hard timeout.',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "actionName",
|
|
95
|
+
type: "string",
|
|
96
|
+
optional: true,
|
|
97
|
+
description:
|
|
98
|
+
"The registry key of the action being called (e.g. `delete-recording`), set at each dispatch site so cross-cutting concerns like the audit log can attribute the call. `undefined` for direct programmatic `run()` calls that bypass the dispatcher.",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "threadId",
|
|
102
|
+
type: "string",
|
|
103
|
+
optional: true,
|
|
104
|
+
description:
|
|
105
|
+
'The agent conversation thread that triggered this call. Populated only when `caller: "tool"`, so the audit log can link a mutation back to the exact agent run.',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "runId",
|
|
109
|
+
type: "string",
|
|
110
|
+
optional: true,
|
|
111
|
+
description:
|
|
112
|
+
'The agent run attempt that triggered this call. Populated only when `caller: "tool"`.',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "turnId",
|
|
116
|
+
type: "string",
|
|
117
|
+
optional: true,
|
|
118
|
+
description:
|
|
119
|
+
'The specific turn within that run that triggered this call. Populated only when `caller: "tool"`.',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "automation",
|
|
123
|
+
type: "ActionAutomationContext",
|
|
124
|
+
optional: true,
|
|
125
|
+
description:
|
|
126
|
+
'Present only when `caller: "automation"`. Carries `triggerId`, `triggerName`, and an optional `policyId` for the event-triggered automation that dispatched this call.',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "networkProtocol",
|
|
130
|
+
type: '"a2a" | "mcp" | "provider-api"',
|
|
131
|
+
optional: true,
|
|
132
|
+
description:
|
|
133
|
+
"Which delegated-call protocol this request arrived over. Set only for those direct-dispatch paths.",
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "networkId",
|
|
137
|
+
type: "string",
|
|
138
|
+
optional: true,
|
|
139
|
+
description:
|
|
140
|
+
"A correlation id for that delegated call, e.g. the A2A delegation JWT id.",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: "networkPeer",
|
|
144
|
+
type: "string",
|
|
145
|
+
optional: true,
|
|
146
|
+
description: "The calling peer's identity for that delegated call.",
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
]}
|
|
151
|
+
returns={{
|
|
152
|
+
type: "Promise<TReturn> | TReturn",
|
|
153
|
+
description:
|
|
154
|
+
"The action's result, validated against `outputSchema` if one is set.",
|
|
155
|
+
}}
|
|
156
|
+
/>
|
|
157
|
+
|
|
158
|
+
`run()` stays backward compatible: existing 1-argument handlers and handlers that only destructure `{ send }` continue to work unchanged.
|
|
159
|
+
|
|
160
|
+
### The `caller` union {#caller}
|
|
161
|
+
|
|
162
|
+
`caller` is the union `"tool" | "http" | "frontend" | "cli" | "mcp" | "a2a" | "automation"`:
|
|
163
|
+
|
|
164
|
+
| `caller` | Set when… |
|
|
165
|
+
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
166
|
+
| `"tool"` | The in-app agent loop, a sub-agent or agent team, or natural-language cross-app A2A delegation, which drives the same agent loop, so its tool calls are `"tool"`. |
|
|
167
|
+
| `"frontend"` | A browser call via `useActionMutation()`, `useActionQuery()`, or `callAction()` (tagged with the `X-Agent-Native-Frontend: 1` header). |
|
|
168
|
+
| `"http"` | A bare programmatic `POST` or `GET` to `/_agent-native/actions/<name>` without the frontend marker. |
|
|
169
|
+
| `"cli"` | `pnpm action <name>` (the CLI runner). |
|
|
170
|
+
| `"mcp"` | An external agent over the MCP `tools/call` endpoint. |
|
|
171
|
+
| `"a2a"` | A direct HTTP call to `/_agent-native/actions/<name>` carrying a signed A2A delegation token. This is an explicitly exposed, cross-app dispatch, distinct from the natural-language `"tool"` path above. |
|
|
172
|
+
| `"automation"` | An event-triggered automation dispatched from a stored workspace trigger. `ctx.automation` carries the trigger lineage. See [Automations](/docs/automations). |
|
|
173
|
+
|
|
174
|
+
## What's next
|
|
175
|
+
|
|
176
|
+
- [**Access & Authorization**](/docs/actions-access-control) — the `ctx.userEmail`/`ctx.orgId` scoping pattern this context enables
|
|
177
|
+
- [**Defining Actions**](/docs/actions-defining) — `defineAction()` anatomy and HTTP config
|
|
178
|
+
- [**Other Surfaces**](/docs/actions-other-surfaces) — how CLI, A2A, MCP, and automation callers set `caller`
|
|
179
|
+
- [**Audit Log**](/docs/audit-log) — how `threadId`/`runId`/`turnId` link a mutation back to its agent run
|
|
180
|
+
- [**Automations**](/docs/automations) — the `ctx.automation` trigger lineage
|
|
@@ -591,7 +591,7 @@ tool-result metadata. Start there when wiring an external agent into the chat.
|
|
|
591
591
|
|
|
592
592
|
<Cards>
|
|
593
593
|
|
|
594
|
-
### [Actions](/docs/actions)
|
|
594
|
+
### [Actions](/docs/actions-overview)
|
|
595
595
|
|
|
596
596
|
Define the operation once. Every surface above calls the same one.
|
|
597
597
|
|
|
@@ -328,4 +328,4 @@ When a sub-agent is at or below the cap, the framework injects a line into its r
|
|
|
328
328
|
|
|
329
329
|
- [**Agent Resources — Custom Agents**](/docs/agent-resources#custom-agents) — the profile format
|
|
330
330
|
- [**A2A Protocol**](/docs/a2a-protocol) — when the "sub-agent" lives in a different app entirely
|
|
331
|
-
- [**Actions**](/docs/actions) — the tools a sub-agent calls
|
|
331
|
+
- [**Actions**](/docs/actions-overview) — the tools a sub-agent calls
|
|
@@ -212,6 +212,6 @@ The audit exits non-zero if a required public surface is missing.
|
|
|
212
212
|
|
|
213
213
|
## What's next
|
|
214
214
|
|
|
215
|
-
- [**Actions**](/docs/actions) — how to opt actions into the public agent protocol
|
|
215
|
+
- [**Actions**](/docs/actions-overview) — how to opt actions into the public agent protocol
|
|
216
216
|
- [**MCP Protocol**](/docs/mcp-protocol) — the MCP surface that `publicMcp: true` enables
|
|
217
217
|
- [**Deployment**](/docs/deployment) — where these static files are written during builds
|
|
@@ -182,7 +182,7 @@ Configure via environment:
|
|
|
182
182
|
|
|
183
183
|
## What's next
|
|
184
184
|
|
|
185
|
-
- [**Actions**](/docs/actions) — the `defineAction` seam where capture happens
|
|
185
|
+
- [**Actions**](/docs/actions-overview) — the `defineAction` seam where capture happens
|
|
186
186
|
- [**Human-in-the-Loop Approvals**](/docs/human-approval) — gated actions, recorded as `denied`
|
|
187
187
|
- [**Security & Data Scoping**](/docs/security) — the ownership model audit reads reuse
|
|
188
188
|
- [**Observability**](/docs/observability) — agent-run telemetry (the other "what happened")
|
|
@@ -119,5 +119,5 @@ See [Zapier REST Hook triggers](https://docs.zapier.com/integrations/build/hook-
|
|
|
119
119
|
|
|
120
120
|
- [**Automations**](/docs/automations#web-request) — the ad-hoc `web-request` tool for one-off outbound HTTP, the lighter-weight sibling to a configured connector
|
|
121
121
|
- [**Messaging**](/docs/messaging) — reaching the agent from Slack, email, Telegram, and WhatsApp, the queue-and-processor pattern this page's callbacks reuse
|
|
122
|
-
- [**Actions**](/docs/actions) — `defineAction`, `needsApproval`, and the action surface `createInvokeAutomationWorkflowAction` builds on
|
|
122
|
+
- [**Actions**](/docs/actions-overview) — `defineAction`, `needsApproval`, and the action surface `createInvokeAutomationWorkflowAction` builds on
|
|
123
123
|
- [**Security**](/docs/security) — `${keys.NAME}` secret substitution and the credential-scoping model this runtime relies on
|
|
@@ -450,7 +450,7 @@ for the full `plan.commented` payload reference and all four plan events.
|
|
|
450
450
|
## What's next
|
|
451
451
|
|
|
452
452
|
- [**Recurring Jobs**](/docs/recurring-jobs) — legacy compatibility and advanced scheduled-job fields
|
|
453
|
-
- [**Actions**](/docs/actions) — automations can call any registered action via the agent loop
|
|
453
|
+
- [**Actions**](/docs/actions-overview) — automations can call any registered action via the agent loop
|
|
454
454
|
- [**Workflow Connectors**](/docs/automation-connectors) — pre-configured n8n/Zapier-style workflow invocation, for when ad-hoc `web-request` isn't a strict enough contract
|
|
455
455
|
- [**Security**](/docs/security) — input validation and secret handling
|
|
456
456
|
- [**Events and Automations**](/docs/template-plan-automations) — the Plan event reference and automation recipes
|
|
@@ -124,5 +124,5 @@ A new curated blueprint under an existing kind needs no code — but if you crea
|
|
|
124
124
|
## What's next
|
|
125
125
|
|
|
126
126
|
- [**Sandbox Adapters**](/docs/sandbox-adapters) — the seam the `add sandbox docker` blueprint targets
|
|
127
|
-
- [**Actions**](/docs/actions) — the single source of truth every blueprint builds on
|
|
127
|
+
- [**Actions**](/docs/actions-overview) — the single source of truth every blueprint builds on
|
|
128
128
|
- [**External Agents**](/docs/external-agents) — connecting the coding agent you pipe blueprints into
|
|
@@ -169,4 +169,4 @@ CLI adapters use `node:child_process`, which does not exist on edge/worker runti
|
|
|
169
169
|
## What's next
|
|
170
170
|
|
|
171
171
|
- [**Adapters**](/docs/sandbox-adapters) — the canonical guide to both adapter seams.
|
|
172
|
-
- [**Actions**](/docs/actions) — the action surface CLI adapters are usually wrapped in.
|
|
172
|
+
- [**Actions**](/docs/actions-overview) — the action surface CLI adapters are usually wrapped in.
|
|
@@ -37,7 +37,7 @@ The user experience is as follows:
|
|
|
37
37
|
|
|
38
38
|
1. The user picks **Offer a refund**, which causes `sendDraftRequest()` to send the prompt and ticket context to the agent.
|
|
39
39
|
|
|
40
|
-
1. The agent calls the `draft-ticket-reply` [action](/docs/actions), and the drafted reply appears in the reply composer.
|
|
40
|
+
1. The agent calls the `draft-ticket-reply` [action](/docs/actions-overview), and the drafted reply appears in the reply composer.
|
|
41
41
|
|
|
42
42
|
## askUserQuestion(opts) {#ask-user-question}
|
|
43
43
|
|
|
@@ -5,7 +5,7 @@ description: "The action hooks app/ uses to read, write, and stay live-synced wi
|
|
|
5
5
|
|
|
6
6
|
# Data & Sync
|
|
7
7
|
|
|
8
|
-
The primary way to read and write app data from client application is through [action](/docs/actions) hooks. By embedding requests into actions, both your client and agent can interact with your application in the same way.
|
|
8
|
+
The primary way to read and write app data from client application is through [action](/docs/actions-overview) hooks. By embedding requests into actions, both your client and agent can interact with your application in the same way.
|
|
9
9
|
|
|
10
10
|
In the example below, a ticket is assigned to the current user manually through a dropdown, and then through the chat agent. Both the UI and agent access the same action.
|
|
11
11
|
|
|
@@ -426,7 +426,7 @@ For normal CRUD, prefer `useActionQuery()` and `useActionMutation()`. Mutating a
|
|
|
426
426
|
|
|
427
427
|
- [**Overview**](/docs/client-overview) — the `app/` and `public/` directory layout this page's hooks live in
|
|
428
428
|
- [**Agent Chat**](/docs/client-agent-chat) — sending prompts and staging context for the agent
|
|
429
|
-
- [**Actions**](/docs/actions) — the `defineAction` surface behind every hook on this page
|
|
429
|
+
- [**Actions**](/docs/actions-overview) — the `defineAction` surface behind every hook on this page
|
|
430
430
|
- [**Advanced**](/docs/client-advanced) — direct `application_state` access
|
|
431
431
|
- [**Sync Internals**](/docs/client-sync-internals) — syncing a raw `useQuery` with `useChangeVersion`
|
|
432
432
|
- [**Real-Time Sync**](/docs/key-concepts#polling-sync) — how `useDbSync` keeps the UI current
|
|
@@ -92,7 +92,7 @@ The one architectural difference from a typical frontend: this layer has no back
|
|
|
92
92
|
|
|
93
93
|
## Where the Client Fits {#role}
|
|
94
94
|
|
|
95
|
-
Browser requests, the agent loop, and external API clients all resolve to the same actions and the same SQL database — there is no separate "app backend" this layer talks to that the agent can't also reach. Building a feature here means building a UI on top of an operation the agent already has, or defining a new action and getting a UI for it at the same time. See [Actions](/docs/actions) for the operation side of that contract.
|
|
95
|
+
Browser requests, the agent loop, and external API clients all resolve to the same actions and the same SQL database — there is no separate "app backend" this layer talks to that the agent can't also reach. Building a feature here means building a UI on top of an operation the agent already has, or defining a new action and getting a UI for it at the same time. See [Actions](/docs/actions-overview) for the operation side of that contract.
|
|
96
96
|
|
|
97
97
|
This page covers the directories you build in and the pieces of the browser runtime nothing else documents (`root.tsx`, `public/`). The React hooks that connect your components to actions and to the agent live on their own focused pages:
|
|
98
98
|
|
|
@@ -201,6 +201,6 @@ import { cn } from "@agent-native/toolkit/utils";
|
|
|
201
201
|
- [**Sync Internals**](/docs/client-sync-internals) — `useChangeVersion` for syncing a raw `useQuery`
|
|
202
202
|
- [**Entry Points**](/docs/client-entry-points) — SSR bootstrap customization
|
|
203
203
|
- [**Routing**](/docs/client-routing) — file-based pages, dynamic params, and navigation
|
|
204
|
-
- [**Actions**](/docs/actions) — the `defineAction` surface behind every data hook
|
|
204
|
+
- [**Actions**](/docs/actions-overview) — the `defineAction` surface behind every data hook
|
|
205
205
|
- [**Custom Design Systems**](/docs/custom-design-system) — swapping in your own component library via `app/design-system.ts`
|
|
206
206
|
- [**Authentication**](/docs/authentication) — the session checks `AppProviders` runs on private paths
|
|
@@ -526,7 +526,7 @@ reasoning.
|
|
|
526
526
|
|
|
527
527
|
- [**Drop-in Agent**](/docs/drop-in-agent) — mount `<AgentSidebar>` and `<AgentPanel>` with a tutorial-first walkthrough
|
|
528
528
|
- [**Native Chat UI**](/docs/native-chat-ui) — the action result contract behind data widgets and custom renderers
|
|
529
|
-
- [**Actions**](/docs/actions) — `defineAction()`, schemas, and the action surface these components call
|
|
529
|
+
- [**Actions**](/docs/actions-overview) — `defineAction()`, schemas, and the action surface these components call
|
|
530
530
|
- [**Real-Time Collaboration**](/docs/real-time-collaboration) — the collab hooks and presence components in depth
|
|
531
531
|
- [**Sharing**](/docs/sharing) — `<ShareButton>` and `<ShareDialog>` wiring for ownable resources
|
|
532
532
|
- [**Toolkit piece: Toolkit UI Primitives**](/docs/toolkit-ui) — the shared shadcn-style building blocks and app-adapter pattern behind these exports
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Cross-App SSO"
|
|
3
|
-
description: "Sign in once across every hosted agent-native app via identity federation with Dispatch as the identity authority
|
|
3
|
+
description: "Sign in once across every hosted agent-native app via identity federation with Dispatch as the identity authority. Canonical hosted clients are enabled by exact origin; self-hosted apps opt in with one env var."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Cross-App SSO
|
|
@@ -233,16 +233,20 @@ trust boundary.
|
|
|
233
233
|
|
|
234
234
|
5. **App mints a normal local session.** From here on the user has an ordinary local session in that app's own store — every existing access check, org scoping, and action guard works exactly as before. The federation only happened at the front door.
|
|
235
235
|
|
|
236
|
-
###
|
|
236
|
+
### Hosted and self-hosted behavior {#opt-in}
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
Canonical hosted client apps use Dispatch automatically when their deployment has
|
|
239
|
+
one of the exact registered `*.agent-native.com` origins. Dispatch is the
|
|
240
|
+
identity authority, not a client, so it never federates to itself. Self-hosted
|
|
241
|
+
apps remain opt-in and must set this environment variable on their deployment:
|
|
239
242
|
|
|
240
243
|
```bash
|
|
241
244
|
AGENT_NATIVE_IDENTITY_HUB_URL=https://dispatch.agent-native.com
|
|
242
245
|
```
|
|
243
246
|
|
|
244
|
-
- **
|
|
245
|
-
- **
|
|
247
|
+
- **Canonical hosted client** → the app shows a **"Sign in with Agent-Native"** option that runs the flow above. Direct local login (email/password, Google) still works alongside it.
|
|
248
|
+
- **Self-hosted with the variable set** → the app shows the same option, using the configured Dispatch instance.
|
|
249
|
+
- **Self-hosted with the variable unset** → **zero behavior change.** The app authenticates exactly as it did before; the federation code path is dormant. There is no schema change and nothing to migrate.
|
|
246
250
|
|
|
247
251
|
## Security {#security}
|
|
248
252
|
|
|
@@ -262,7 +266,7 @@ The whole model rests on a few deliberately small guarantees:
|
|
|
262
266
|
accept a user id, role, org membership, or any privileged state from the
|
|
263
267
|
wire — it derives everything locally from the matched account.
|
|
264
268
|
- **Additive-only identity writes.** Linking either reuses an existing same-email account untouched or inserts a new one. No update, rename, repoint, or delete of identity rows ever happens on this path.
|
|
265
|
-
- **
|
|
269
|
+
- **Exact-origin trust.** Only the registered canonical hosted client origins get the implicit hosted default. Self-hosted and custom origins remain opt-in through `AGENT_NATIVE_IDENTITY_HUB_URL`; the separately gated packaged Desktop path is described below.
|
|
266
270
|
|
|
267
271
|
<Callout id="doc-block-18qhl3m" tone="success">
|
|
268
272
|
|
|
@@ -345,8 +349,8 @@ flag controls whether Desktop may begin the ceremony; it does not authorize a
|
|
|
345
349
|
user or weaken nonce, signature, origin, callback, app-binding, cookie,
|
|
346
350
|
revocation, or credential-custody checks. With the flag Off or unavailable,
|
|
347
351
|
Desktop leaves ordinary per-app sign-in, sign-out, and Settings unchanged.
|
|
348
|
-
Canonical hosted apps recognize the packaged Desktop request
|
|
349
|
-
`AGENT_NATIVE_IDENTITY_HUB_URL` on every deployment;
|
|
352
|
+
Canonical hosted apps recognize the packaged Desktop request and ordinary web
|
|
353
|
+
browsers without requiring `AGENT_NATIVE_IDENTITY_HUB_URL` on every deployment;
|
|
350
354
|
self-hosted apps still require that explicit configuration.
|
|
351
355
|
Stable Desktop builds do not initialize the broker until a later release is
|
|
352
356
|
separately approved.
|
|
@@ -379,19 +383,22 @@ Without an exact custom registry entry, a self-hosted Dispatch can only issue co
|
|
|
379
383
|
|
|
380
384
|
## Canary rollout runbook {#canary-rollout}
|
|
381
385
|
|
|
382
|
-
|
|
386
|
+
Canonical hosted clients take the default after the release ships. Self-hosted
|
|
387
|
+
and custom deployments still use **a single environment variable per app**.
|
|
388
|
+
Roll out one deployment at a time, verify, then expand.
|
|
383
389
|
|
|
384
|
-
**1. Deploy the code
|
|
385
|
-
Ship the release to
|
|
390
|
+
**1. Deploy the code and verify a canonical hosted client.**
|
|
391
|
+
Ship the release to the canonical apps. Confirm normal logins still work on a
|
|
392
|
+
couple of apps and that the new sign-in option appears on a client app.
|
|
386
393
|
|
|
387
|
-
**2. Enable
|
|
394
|
+
**2. Enable self-hosted/custom apps one at a time.**
|
|
388
395
|
Set, on one deployment only:
|
|
389
396
|
|
|
390
397
|
```bash
|
|
391
398
|
AGENT_NATIVE_IDENTITY_HUB_URL=https://dispatch.agent-native.com
|
|
392
399
|
```
|
|
393
400
|
|
|
394
|
-
Leave every other app's environment unset. Redeploy/restart so it picks up the variable.
|
|
401
|
+
Leave every other self-hosted app's environment unset. Redeploy/restart so it picks up the variable.
|
|
395
402
|
|
|
396
403
|
**3. Verify the canary (checklist).**
|
|
397
404
|
|
|
@@ -402,13 +409,13 @@ Leave every other app's environment unset. Redeploy/restart so it picks up the v
|
|
|
402
409
|
- **App data is intact** — your existing records, settings, and org scoping are exactly as they were.
|
|
403
410
|
- **Existing direct logins still work** — email/password and Google sign-in continue to function alongside SSO.
|
|
404
411
|
|
|
405
|
-
If any check fails, go straight to step
|
|
412
|
+
If any check fails, go straight to step 5 (rollback) — it is instant and data-safe.
|
|
406
413
|
|
|
407
414
|
**4. Expand app-by-app.**
|
|
408
|
-
Once one
|
|
415
|
+
Once one deployment is verified, repeat steps 2–3 for the next one. Never batch-enable custom origins.
|
|
409
416
|
|
|
410
|
-
**5. Rollback
|
|
411
|
-
|
|
417
|
+
**5. Rollback.**
|
|
418
|
+
For a self-hosted app, **remove `AGENT_NATIVE_IDENTITY_HUB_URL` from its environment and redeploy/restart it.** A canonical hosted client can be rolled back by reverting the release or disabling the hosted client path. There is **no data change to undo** — identity rows were only ever added. Each deployment's cutover and rollback are independent and reversible.
|
|
412
419
|
|
|
413
420
|
<Callout tone="info">
|
|
414
421
|
|
|
@@ -14,7 +14,7 @@ search: "data program emit rows schema providerFetch dashboard panel program sou
|
|
|
14
14
|
|
|
15
15
|
A **data program** is a named, stored, agent-authored JS script that fetches, joins, filters, or aggregates data — provider APIs via `providerFetch` / `providerFetchAll` / `providerSearchAll`, app data via `appAction`, or Resources-backed workspace files — and calls `emit(rows, schema)` exactly once with the result. The result is cached in SQL and any chart/table component can render it, refreshed on a policy you choose instead of on every page view.
|
|
16
16
|
|
|
17
|
-
It ships automatically wherever [`run-code`](/docs/actions) is available — there is nothing to mount or configure per app. If your app already has run-code enabled, `save-data-program`, `preview-data-program`, `run-data-program`, `list-data-programs`, `get-data-program`, and `delete-data-program` are already registered actions.
|
|
17
|
+
It ships automatically wherever [`run-code`](/docs/actions-overview) is available — there is nothing to mount or configure per app. If your app already has run-code enabled, `save-data-program`, `preview-data-program`, `run-data-program`, `list-data-programs`, `get-data-program`, and `delete-data-program` are already registered actions.
|
|
18
18
|
|
|
19
19
|
<Diagram id="doc-block-dp-overview" title="From ad-hoc query to live panel" summary="A run-code script becomes a stored program once it calls emit(); any dashboard panel can bind to it and the cache/refresh policy takes over from there.">
|
|
20
20
|
|
|
@@ -330,6 +330,6 @@ Any app can implement the same adoption for its own dashboards/tables: call `run
|
|
|
330
330
|
## What's next {#whats-next}
|
|
331
331
|
|
|
332
332
|
- [Extensions](/docs/extensions) — the sandboxed mini-app primitive data programs share a security posture and sharing model with, but with a UI of its own.
|
|
333
|
-
- [Actions](/docs/actions) — the `run-code` conventions and sandbox globals (`providerFetch`, `appAction`, etc.) data programs are built on.
|
|
333
|
+
- [Actions](/docs/actions-overview) — the `run-code` conventions and sandbox globals (`providerFetch`, `appAction`, etc.) data programs are built on.
|
|
334
334
|
- [Sharing & Privacy](/docs/sharing) — the org-internal, never-public sharing model data programs use.
|
|
335
335
|
- [Security](/docs/security) — the framework's credential-handling and access-scoping invariants.
|