@agent-native/core 0.157.4 → 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.
Files changed (60) hide show
  1. package/docs/content/actions-access-control.mdx +226 -0
  2. package/docs/content/actions-advanced.mdx +152 -0
  3. package/docs/content/actions-defining.mdx +275 -0
  4. package/docs/content/actions-other-surfaces.mdx +167 -0
  5. package/docs/content/actions-overview.mdx +214 -0
  6. package/docs/content/actions-run-context.mdx +180 -0
  7. package/docs/content/agent-surfaces.mdx +1 -1
  8. package/docs/content/agent-teams.mdx +1 -1
  9. package/docs/content/agent-web-surfaces.mdx +1 -1
  10. package/docs/content/audit-log.mdx +1 -1
  11. package/docs/content/automation-connectors.mdx +1 -1
  12. package/docs/content/automations.mdx +1 -1
  13. package/docs/content/blueprint-installer.mdx +1 -1
  14. package/docs/content/cli-adapters.mdx +1 -1
  15. package/docs/content/client-agent-chat.mdx +1 -1
  16. package/docs/content/client-data.mdx +2 -2
  17. package/docs/content/client-overview.mdx +2 -2
  18. package/docs/content/components.mdx +1 -1
  19. package/docs/content/data-programs.mdx +2 -2
  20. package/docs/content/database.mdx +1 -1
  21. package/docs/content/deployment.mdx +1 -1
  22. package/docs/content/docs-components.mdx +14 -3
  23. package/docs/content/drop-in-agent.mdx +2 -2
  24. package/docs/content/durable-resume.mdx +1 -1
  25. package/docs/content/evals.mdx +1 -1
  26. package/docs/content/extensions.mdx +1 -1
  27. package/docs/content/external-agents-catalog.mdx +2 -2
  28. package/docs/content/external-agents.mdx +1 -1
  29. package/docs/content/generative-ui.mdx +1 -1
  30. package/docs/content/getting-started.mdx +1 -1
  31. package/docs/content/http-api.mdx +4 -4
  32. package/docs/content/human-approval.mdx +1 -1
  33. package/docs/content/key-concepts.mdx +1 -1
  34. package/docs/content/mcp-apps.mdx +1 -1
  35. package/docs/content/mcp-clients.mdx +1 -1
  36. package/docs/content/mcp-protocol.mdx +1 -1
  37. package/docs/content/native-chat-ui.mdx +1 -1
  38. package/docs/content/observability.mdx +1 -1
  39. package/docs/content/organizations-teams-permissions.mdx +1 -1
  40. package/docs/content/processors.mdx +1 -1
  41. package/docs/content/pure-agent-apps.mdx +1 -1
  42. package/docs/content/recurring-jobs.mdx +1 -1
  43. package/docs/content/server-database.mdx +1 -1
  44. package/docs/content/server-overview.mdx +3 -3
  45. package/docs/content/server-routes.mdx +2 -2
  46. package/docs/content/template-analytics-developers.mdx +1 -1
  47. package/docs/content/template-assets-developers.mdx +1 -1
  48. package/docs/content/template-brain-developers.mdx +1 -1
  49. package/docs/content/template-calendar-developers.mdx +1 -1
  50. package/docs/content/template-chat-first-edits.mdx +1 -1
  51. package/docs/content/template-chat.mdx +1 -1
  52. package/docs/content/template-content-developers.mdx +1 -1
  53. package/docs/content/template-forms-developers.mdx +1 -1
  54. package/docs/content/template-forms.mdx +1 -1
  55. package/docs/content/template-mail-developers.mdx +2 -2
  56. package/docs/content/toolkit-org-team.mdx +1 -1
  57. package/docs/content/tracking.mdx +1 -1
  58. package/docs/content/what-is-agent-native.mdx +1 -1
  59. package/package.json +1 -1
  60. package/docs/content/actions.mdx +0 -750
@@ -0,0 +1,167 @@
1
+ ---
2
+ title: "Other Surfaces"
3
+ description: "Everything that calls an action beyond the UI hooks: native chat UI widget results, the CLI, A2A, MCP, and the two standard actions every template ships."
4
+ ---
5
+
6
+ # Other Surfaces
7
+
8
+ The UI-hook surface is covered on [Data & Sync](/docs/client-data): `useActionQuery()`, `useActionMutation()`, and `callAction()`. This page covers everything else that can call, or be driven by, an action.
9
+
10
+ ## Rendering native chat UI {#native-chat-ui}
11
+
12
+ Actions can return structured widget data that the in-app chat renders
13
+ natively. This is the first-party chat path for reusable tables, charts, setup
14
+ summaries, and insight cards. Use [Generative UI](/docs/generative-ui) when the
15
+ agent needs to generate arbitrary interactive controls inside the in-app chat,
16
+ and use [MCP Apps](/docs/mcp-apps) for inline UI in external MCP hosts.
17
+
18
+ ```ts
19
+ import { defineAction } from "@agent-native/core/action";
20
+ import { ACTION_CHAT_UI_DATA_CHART_RENDERER } from "@agent-native/core/action-ui";
21
+ import {
22
+ createDataChartWidgetResult,
23
+ dataChartWidgetResultSchema,
24
+ } from "@agent-native/core/data-widgets";
25
+
26
+ export default defineAction({
27
+ description: "Summarize response trends.",
28
+ readOnly: true,
29
+ outputSchema: dataChartWidgetResultSchema,
30
+ chatUI: { renderer: ACTION_CHAT_UI_DATA_CHART_RENDERER },
31
+ run: async () =>
32
+ createDataChartWidgetResult({
33
+ title: "Response trends",
34
+ chartSeries: {
35
+ type: "line",
36
+ xKey: "day",
37
+ series: [{ key: "responses", label: "Responses" }],
38
+ data: [
39
+ { day: "Mon", responses: 12 },
40
+ { day: "Tue", responses: 18 },
41
+ ],
42
+ },
43
+ }),
44
+ });
45
+ ```
46
+
47
+ The built-in discriminants are `"data-table"`, `"data-chart"`, and
48
+ `"data-insights"`, with server-safe builders and schemas in
49
+ `@agent-native/core/data-widgets`. Use `data-chart` for chart-only answers,
50
+ `data-table` for SQL/list results, and `data-insights` only when a combined
51
+ summary/chart/table card is the right output. See
52
+ [Native Chat UI](/docs/native-chat-ui) for the full result contract, or
53
+ [BYO agent runtimes](/docs/native-chat-ui#byo-agent-runtimes) if you're
54
+ wiring a custom agent runtime instead of the built-in chat loop. See
55
+ [Agent Surfaces](/docs/agent-surfaces) for how the same action can stay
56
+ automation-friendly, render in chat, or grow into a full screen.
57
+
58
+ ## Calling it from the CLI {#cli}
59
+
60
+ Every action is runnable via `pnpm action`:
61
+
62
+ ```bash
63
+ pnpm action reply-to-email '{"emailId":"thread-123","body":"Thanks!"}'
64
+ ```
65
+
66
+ JSON input is the preferred shape for agents and complex objects. Flags work
67
+ the same way for simple manual runs and existing scripts:
68
+
69
+ ```bash
70
+ pnpm action reply-to-email --emailId thread-123 --body "Thanks!"
71
+ ```
72
+
73
+ This is useful for agent-dev loops, scripts, and cron jobs.
74
+
75
+ ## Calling it from another agent (A2A) {#a2a}
76
+
77
+ If your app is an [A2A](/docs/a2a-protocol) peer, other agent-native apps discover your actions automatically and can call them by name. Same-origin deploys skip JWT signing. Cross-origin deploys use a shared `A2A_SECRET` instead.
78
+
79
+ ## Exposing it over MCP {#mcp}
80
+
81
+ With MCP enabled, your actions show up in the framework's MCP server at `/mcp`. Every caller gets a compact catalog by default (app-facing builtins plus the template-declared app actions), and `tool-search` is always present so any other tool stays reachable on demand. The full action surface is served only on explicit opt-in (`--full-catalog` token or `AGENT_NATIVE_MCP_FULL_CATALOG=1`), and [`publicAgent.expose`](/docs/actions-access-control#public-agent) opts a safe read/ingest tool onto the public surface. See [MCP Protocol](/docs/mcp-protocol) for catalog tiers, auth, and the `mcpApp` resource details.
82
+
83
+ For UI-capable MCP hosts, an action can declare an optional MCP Apps resource via the `mcpApp` field (plus a matching `link`) so capable hosts render the result inline. When `link` and `mcpApp` should point at the same route, `embedRoute()` builds both from one pure path builder:
84
+
85
+ ```ts
86
+ import { embedRoute } from "@agent-native/core";
87
+
88
+ export default defineAction({
89
+ description: "Create an email draft for review.",
90
+ schema: z.object({ body: z.string() }),
91
+ run: async ({ body }) => ({ body }),
92
+ ...embedRoute({
93
+ title: "Review draft",
94
+ openLabel: "Open in Mail",
95
+ path: ({ result }) => ({
96
+ label: "Open draft in Mail",
97
+ url: "/_agent-native/open?app=mail&view=inbox",
98
+ }),
99
+ }),
100
+ });
101
+ ```
102
+
103
+ Keep `link` as the fallback for CLI and non-UI MCP hosts. It is also the embed's launch target. The embed bridge (the signed embed-start session, transplant vs. controlled-frame rendering, the `ui/*` host bridge, CSP, and height clamping) is owned by [External Agents](/docs/external-agents#mcp-app-bridge).
104
+
105
+ ## Standard actions {#standard-actions}
106
+
107
+ Every template should include these two for [context awareness](/docs/context-awareness).
108
+
109
+ ### view-screen {#view-screen}
110
+
111
+ Reads the current navigation state, fetches contextual data, and returns a snapshot of what the user sees. The agent calls this when it needs a fresh look at the screen.
112
+
113
+ ```ts
114
+ // actions/view-screen.ts
115
+ import { defineAction } from "@agent-native/core/action";
116
+ import { readAppState } from "@agent-native/core/application-state";
117
+ import { z } from "zod";
118
+
119
+ export default defineAction({
120
+ description: "Read the current screen state for context.",
121
+ schema: z.object({}),
122
+ http: { method: "GET" },
123
+ run: async () => {
124
+ const navigation = await readAppState("navigation");
125
+ const screen: Record<string, unknown> = { navigation };
126
+
127
+ if (navigation?.view === "inbox") {
128
+ screen.emailList = await listEmailsForLabel(navigation.label);
129
+ }
130
+
131
+ return screen;
132
+ },
133
+ });
134
+ ```
135
+
136
+ ### navigate {#navigate}
137
+
138
+ Writes a one-shot navigation command to application state. The UI reads it, navigates, and deletes the entry.
139
+
140
+ ```ts
141
+ // actions/navigate.ts
142
+ import { defineAction } from "@agent-native/core/action";
143
+ import { writeAppState } from "@agent-native/core/application-state";
144
+ import { z } from "zod";
145
+
146
+ export default defineAction({
147
+ description: "Navigate the user to a view.",
148
+ schema: z.object({
149
+ view: z.string(),
150
+ threadId: z.string().optional(),
151
+ }),
152
+ run: async (args) => {
153
+ await writeAppState("navigate", args);
154
+ return { ok: true };
155
+ },
156
+ });
157
+ ```
158
+
159
+ ## What's next
160
+
161
+ - [**Data & Sync**](/docs/client-data) — `useActionQuery`, `useActionMutation`, and `callAction` from the UI
162
+ - [**Overview**](/docs/actions-overview) — what an action is and the hello-world walkthrough
163
+ - [**Context Awareness**](/docs/context-awareness) — the `view-screen` + `navigate` pattern in depth
164
+ - [**A2A Protocol**](/docs/a2a-protocol) — how other agents discover and call your actions
165
+ - [**MCP Protocol**](/docs/mcp-protocol) — catalog tiers, auth, and `mcpApp` resources
166
+ - [**Generative UI**](/docs/generative-ui) — rendering transient or persisted generated UI inline in chat
167
+ - [**Native Chat UI**](/docs/native-chat-ui) — the full widget result contract
@@ -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">&#8595;</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">&#8595;</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">&#8595;</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">&#8595;</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