@agent-native/core 0.227.0-nightly-20261110182415 → 0.227.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/agent/default-agent-engine.d.ts +1 -0
  2. package/dist/agent/default-agent-engine.js +6 -3
  3. package/dist/agent/engine/builder-engine.js +10 -6
  4. package/dist/agent/engine/chat-model-availability.d.ts +9 -0
  5. package/dist/agent/engine/chat-model-availability.js +39 -0
  6. package/dist/agent/optional-placeholders.d.ts +1 -0
  7. package/dist/agent/optional-placeholders.js +3 -0
  8. package/dist/cli/index.js +1 -1
  9. package/dist/client/chat/agentkit-protocol.js +259 -200
  10. package/dist/client/chat/run-outcome.d.ts +48 -0
  11. package/dist/client/chat/run-outcome.js +50 -0
  12. package/dist/collab/routes.d.ts +1 -1
  13. package/dist/collab/struct-routes.d.ts +1 -1
  14. package/dist/framework-package-versions.json +11 -11
  15. package/dist/jobs/run-now.js +9 -1
  16. package/dist/notifications/routes.d.ts +3 -3
  17. package/dist/org/index.d.ts +1 -1
  18. package/dist/org/migrations.d.ts +1 -1
  19. package/dist/provider-api/actions/provider-api.d.ts +1 -1
  20. package/dist/resources/handlers.d.ts +1 -1
  21. package/dist/scripts/agent-engines/list-agent-engines.js +9 -5
  22. package/dist/server/index.d.ts +1 -0
  23. package/dist/server/index.js +1 -0
  24. package/dist/templates/builder-code-starter/AGENTS.md.patch +1 -1
  25. package/dist/templates/chat/AGENTS.md +1 -1
  26. package/dist/triggers/actions/list-automations.js +7 -1
  27. package/docs/content/agent-web-surfaces.mdx +54 -42
  28. package/docs/content/create-with-an-agent.mdx +1 -1
  29. package/docs/content/external-agents.mdx +8 -0
  30. package/package.json +4 -4
  31. package/src/templates/builder-code-starter/AGENTS.md.patch +1 -1
  32. package/src/templates/chat/AGENTS.md +1 -1
@@ -15,6 +15,54 @@ import { type AutoContinueRefusalCode } from "../../agent/auto-continue.js";
15
15
  */
16
16
  export declare const RUN_OUTCOMES: readonly ["running", "succeeded", "stopped", "interrupted", "failed", "unverified"];
17
17
  export type RunOutcome = (typeof RUN_OUTCOMES)[number];
18
+ export type ActiveRunPhase = {
19
+ readonly type: "streaming";
20
+ } | {
21
+ readonly type: "holdingInterruption";
22
+ readonly error: AgentError;
23
+ } | {
24
+ readonly type: "followingSuccessor";
25
+ } | {
26
+ readonly type: "awaitingContinuation";
27
+ readonly streamClosed: boolean;
28
+ };
29
+ export type RunPhase = ActiveRunPhase | {
30
+ readonly type: "cancelling";
31
+ readonly previous: ActiveRunPhase;
32
+ } | {
33
+ readonly type: "terminal";
34
+ } | {
35
+ readonly type: "disposed";
36
+ };
37
+ export type RunPhaseEvent = {
38
+ readonly type: "streamEnded";
39
+ } | {
40
+ readonly type: "streamFailed";
41
+ } | {
42
+ readonly type: "interrupted";
43
+ readonly error: AgentError;
44
+ } | {
45
+ readonly type: "followSuccessor";
46
+ } | {
47
+ readonly type: "streamOpened";
48
+ } | {
49
+ readonly type: "continuationResumed";
50
+ } | {
51
+ readonly type: "awaitContinuation";
52
+ readonly streamClosed: boolean;
53
+ } | {
54
+ readonly type: "terminal";
55
+ } | {
56
+ readonly type: "cancelStarted";
57
+ } | {
58
+ readonly type: "cancelSucceeded";
59
+ } | {
60
+ readonly type: "cancelFailed";
61
+ } | {
62
+ readonly type: "dispose";
63
+ };
64
+ /** Late stream and authority results cannot revive a terminal or disposed run. */
65
+ export declare function transition(phase: RunPhase, event: RunPhaseEvent): RunPhase;
18
66
  /**
19
67
  * Codes that described "the agent stopped / is stuck" one incident at a time.
20
68
  * They survive only as telemetry detail; the user sees their outcome. A new
@@ -24,6 +24,56 @@ export const RUN_OUTCOMES = [
24
24
  "failed",
25
25
  "unverified",
26
26
  ];
27
+ /** Late stream and authority results cannot revive a terminal or disposed run. */
28
+ export function transition(phase, event) {
29
+ if (event.type === "dispose")
30
+ return { type: "disposed" };
31
+ if (phase.type === "disposed")
32
+ return phase;
33
+ if (phase.type === "terminal")
34
+ return phase;
35
+ if (phase.type === "cancelling") {
36
+ if (event.type === "cancelFailed")
37
+ return phase.previous;
38
+ if (event.type === "cancelSucceeded")
39
+ return { type: "terminal" };
40
+ return phase;
41
+ }
42
+ switch (event.type) {
43
+ case "streamEnded":
44
+ case "streamFailed":
45
+ return phase.type === "streaming"
46
+ ? { type: "followingSuccessor" }
47
+ : phase;
48
+ case "interrupted":
49
+ return phase.type === "streaming"
50
+ ? { type: "holdingInterruption", error: event.error }
51
+ : phase;
52
+ case "followSuccessor":
53
+ return phase.type === "holdingInterruption"
54
+ ? { type: "followingSuccessor" }
55
+ : phase;
56
+ case "streamOpened":
57
+ return phase.type === "followingSuccessor"
58
+ ? { type: "streaming" }
59
+ : phase;
60
+ case "continuationResumed":
61
+ return phase.type === "awaitingContinuation"
62
+ ? { type: "streaming" }
63
+ : phase;
64
+ case "awaitContinuation":
65
+ return phase.type === "streaming"
66
+ ? { type: "awaitingContinuation", streamClosed: event.streamClosed }
67
+ : phase;
68
+ case "terminal":
69
+ return { type: "terminal" };
70
+ case "cancelStarted":
71
+ return { type: "cancelling", previous: phase };
72
+ case "cancelSucceeded":
73
+ case "cancelFailed":
74
+ return phase;
75
+ }
76
+ }
27
77
  /**
28
78
  * Codes that described "the agent stopped / is stuck" one incident at a time.
29
79
  * They survive only as telemetry detail; the user sees their outcome. A new
@@ -26,8 +26,8 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
26
26
  ok: boolean;
27
27
  }>>;
28
28
  export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
29
- ok?: undefined;
30
29
  text?: undefined;
30
+ ok?: undefined;
31
31
  error: string;
32
32
  } | {
33
33
  error?: undefined;
@@ -13,9 +13,9 @@ export declare const postCollabPatch: import("h3").EventHandlerWithFetch<import(
13
13
  ok: boolean;
14
14
  }>>;
15
15
  export declare const getCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
16
- data?: undefined;
17
16
  error: string;
18
17
  docId?: undefined;
18
+ data?: undefined;
19
19
  } | {
20
20
  error?: undefined;
21
21
  docId: string;
@@ -1,17 +1,17 @@
1
1
  {
2
- "@agent-native/agentkit": "0.227.0-nightly-20261110182415",
2
+ "@agent-native/agentkit": "0.227.0",
3
3
  "@agent-native/code-agents-ui": "0.1.75",
4
- "@agent-native/core": "0.227.0-nightly-20261110182415",
5
- "@agent-native/core-corpus": "0.227.0-nightly-20261110182415",
6
- "@agent-native/creative-context": "0.8.69-nightly-20261110182415",
7
- "@agent-native/dispatch": "0.42.4-nightly-20261110182415",
4
+ "@agent-native/core": "0.227.0",
5
+ "@agent-native/core-corpus": "0.227.0",
6
+ "@agent-native/creative-context": "0.8.69",
7
+ "@agent-native/dispatch": "0.42.4",
8
8
  "@agent-native/embedding": "0.2.0",
9
9
  "@agent-native/migrate": "0.0.7",
10
- "@agent-native/otel": "0.1.35",
11
- "@agent-native/pinpoint": "0.1.111",
12
- "@agent-native/recap-cli": "0.5.99",
13
- "@agent-native/scheduling": "0.2.56-nightly-20261110182415",
10
+ "@agent-native/otel": "0.1.36",
11
+ "@agent-native/pinpoint": "0.1.112",
12
+ "@agent-native/recap-cli": "0.5.100",
13
+ "@agent-native/scheduling": "0.2.56",
14
14
  "@agent-native/shared-app-config": "0.1.2",
15
- "@agent-native/skills": "0.4.4-nightly-20261110182415",
16
- "@agent-native/toolkit": "0.227.0-nightly-20261110182415"
15
+ "@agent-native/skills": "0.4.4",
16
+ "@agent-native/toolkit": "0.227.0"
17
17
  }
@@ -4,7 +4,7 @@ import { canQueueAutomationRunNow, } from "../automations/service.js";
4
4
  import { isLocalDatabase } from "../db/client.js";
5
5
  import { organizationResourceOwner, resourceGetByPath, } from "../resources/store.js";
6
6
  import { fireInternalDispatch } from "../server/self-dispatch.js";
7
- import { parseJobResource } from "./frontmatter.js";
7
+ import { isRecoveredFactoryJob, jobBelongsToApp, parseJobResource, } from "./frontmatter.js";
8
8
  import { automationRunOwnership } from "./run-history-ownership.js";
9
9
  import { listUnclaimedAutomationRuns, startAutomationRun, } from "./run-history.js";
10
10
  async function dispatchAutomationRun(historyId, requestHeaders) {
@@ -113,6 +113,14 @@ export async function authorizeAutomationRunNow(input) {
113
113
  });
114
114
  }
115
115
  if (!(await canQueueAutomationRunNow(input, access.resource, access.scope, input.additionalJobAppIds))) {
116
+ const { meta } = parseJobResource(access.resource.content);
117
+ if (!jobBelongsToApp(meta, input.appId, input.additionalJobAppIds) &&
118
+ !isRecoveredFactoryJob(meta, access.resource.path, input.appId, access.resource.owner)) {
119
+ const ownerAppId = meta.appId?.trim();
120
+ throw Object.assign(new Error(ownerAppId
121
+ ? `This automation belongs to the "${ownerAppId}" app. Run it from that app.`
122
+ : "This automation has no app owner and cannot be run."), { statusCode: 403 });
123
+ }
116
124
  throw Object.assign(new Error("Collaborate access is required to run this automation."), { statusCode: 403 });
117
125
  }
118
126
  return access;
@@ -1,12 +1,12 @@
1
1
  export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
2
- error?: undefined;
3
2
  count: number;
4
3
  updated?: undefined;
4
+ error?: undefined;
5
5
  ok?: undefined;
6
6
  } | {
7
- error?: undefined;
8
7
  count?: undefined;
9
8
  updated: number;
9
+ error?: undefined;
10
10
  ok?: undefined;
11
11
  } | {
12
12
  count?: undefined;
@@ -14,8 +14,8 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
14
14
  error: string;
15
15
  ok?: undefined;
16
16
  } | {
17
- error?: undefined;
18
17
  count?: undefined;
19
18
  updated?: undefined;
19
+ error?: undefined;
20
20
  ok: boolean;
21
21
  }>>;
@@ -180,9 +180,9 @@ export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import(
180
180
  soloDeploymentAdmin: boolean | undefined;
181
181
  }>>;
182
182
  export declare const createOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
183
- id?: undefined;
184
183
  name?: undefined;
185
184
  success: boolean;
185
+ id?: undefined;
186
186
  role?: undefined;
187
187
  } | {
188
188
  success?: undefined;
@@ -1,7 +1,7 @@
1
1
  export declare const ORG_MIGRATIONS: ({
2
- name?: undefined;
3
2
  version: number;
4
3
  sql: string;
4
+ name?: undefined;
5
5
  } | {
6
6
  version: number;
7
7
  name: string;
@@ -316,8 +316,8 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
316
316
  notes?: string | undefined;
317
317
  scope?: "org" | "user" | undefined;
318
318
  }, {
319
- provider?: undefined;
320
319
  id?: undefined;
320
+ provider?: undefined;
321
321
  message?: undefined;
322
322
  providers: {
323
323
  id: string;
@@ -49,7 +49,6 @@ export declare function handleUploadResource(event: any): Promise<import("./stor
49
49
  error: string;
50
50
  storageSetupRequired?: undefined;
51
51
  } | {
52
- error?: undefined;
53
52
  id: string;
54
53
  path: string;
55
54
  owner: string;
@@ -64,6 +63,7 @@ export declare function handleUploadResource(event: any): Promise<import("./stor
64
63
  runId: string | null;
65
64
  expiresAt: number | null;
66
65
  metadata: string | null;
66
+ error?: undefined;
67
67
  url: string;
68
68
  provider: string;
69
69
  storageSetupRequired?: undefined;
@@ -1,6 +1,6 @@
1
1
  import { getAgentAppModelDefaultForCurrentRequest } from "../../agent/app-model-defaults.js";
2
2
  import { CHATGPT_SUBSCRIPTION_ENGINE_NAME } from "../../agent/chatgpt-subscription-contract.js";
3
- import { readDefaultAgentEngineSettingDetailed, resolveDefaultAgentEngineAuthority, } from "../../agent/default-agent-engine.js";
3
+ import { isDefaultAgentEngineScopeResolved, readDefaultAgentEngineSettingDetailed, resolveDefaultAgentEngineAuthority, } from "../../agent/default-agent-engine.js";
4
4
  import { listChatGPTSubscriptionModels } from "../../agent/engine/chatgpt-subscription-engine.js";
5
5
  import { listAgentEngines, registerBuiltinEngines, detectEngineFromEnv, detectEngineFromUserSecrets, getAgentEngineEntry, isAgentEnginePackageInstalled, isStoredEngineUsableForRequest, normalizeModelForEngine, resolveEngineAcceptsCustomModels, resolveEnginePreservesCustomModels, } from "../../agent/engine/index.js";
6
6
  import { applyProviderModelSelection, providerForEngineName, resolveEffectiveProviderModelSelection, } from "../../agent/provider-model-selection.js";
@@ -101,10 +101,14 @@ export async function run(args = {}) {
101
101
  }
102
102
  return pending;
103
103
  };
104
- const [defaultSetting, defaultAuthority] = await Promise.all([
105
- readDefaultAgentEngineSettingDetailed(),
106
- resolveDefaultAgentEngineAuthority(),
107
- ]);
104
+ // An unresolved scope cannot say which default applies. Listing engines
105
+ // must still work, so the read is skipped and reported as "unresolved"
106
+ // instead of "none", which would claim no default is saved.
107
+ const defaultAuthority = await resolveDefaultAgentEngineAuthority();
108
+ const scopeUnresolved = !isDefaultAgentEngineScopeResolved();
109
+ const defaultSetting = scopeUnresolved
110
+ ? { value: null, source: "unresolved" }
111
+ : await readDefaultAgentEngineSettingDetailed();
108
112
  const current = defaultSetting.value
109
113
  ? defaultSetting.value
110
114
  : null;
@@ -41,6 +41,7 @@ export { callerHasThreadAccess } from "../agent/run-ownership.js";
41
41
  export { abortTurnByRefDurably, getActiveRunForThreadAsync, } from "../agent/run-manager.js";
42
42
  export { mountRealtimeVoiceRoutes, realtimeVoiceSafetyIdentifier, REALTIME_VOICE_MAX_SDP_BYTES, REALTIME_VOICE_MAX_TOOL_BODY_BYTES, REALTIME_VOICE_MAX_TOOL_OUTPUT_CHARS, REALTIME_VOICE_SESSION_PATH, REALTIME_VOICE_TOOL_PATH, type MountRealtimeVoiceRoutesOptions, type RealtimeVoiceIntelligence, type RealtimeVoiceRequestContext, type RealtimeVoiceToolExecutionRequest, type RealtimeVoiceToolExecutionResult, } from "./realtime-voice.js";
43
43
  export { getStoredModelForEngine, resolveEngine, } from "../agent/engine/index.js";
44
+ export { resolveChatModelAvailability, type ChatModelAvailability, } from "../agent/engine/chat-model-availability.js";
44
45
  export { completeText, type CompleteTextMessage, type CompleteTextOptions, type CompleteTextResult, type CompleteTextUsage, } from "./complete-text.js";
45
46
  export { createDevScriptRegistry } from "../scripts/dev/index.js";
46
47
  export { createPollHandler, recordChange, prepareTransactionalChange, getVersion, getChangesSince, getCurrentPollBaseline, getPollEmitter, canSeeChangeForUser, POLL_CHANGE_EVENT, type TransactionalChange, } from "./poll.js";
@@ -39,6 +39,7 @@ export { callerHasThreadAccess } from "../agent/run-ownership.js";
39
39
  export { abortTurnByRefDurably, getActiveRunForThreadAsync, } from "../agent/run-manager.js";
40
40
  export { mountRealtimeVoiceRoutes, realtimeVoiceSafetyIdentifier, REALTIME_VOICE_MAX_SDP_BYTES, REALTIME_VOICE_MAX_TOOL_BODY_BYTES, REALTIME_VOICE_MAX_TOOL_OUTPUT_CHARS, REALTIME_VOICE_SESSION_PATH, REALTIME_VOICE_TOOL_PATH, } from "./realtime-voice.js";
41
41
  export { getStoredModelForEngine, resolveEngine, } from "../agent/engine/index.js";
42
+ export { resolveChatModelAvailability, } from "../agent/engine/chat-model-availability.js";
42
43
  export { completeText, } from "./complete-text.js";
43
44
  export { createDevScriptRegistry } from "../scripts/dev/index.js";
44
45
  export { createPollHandler, recordChange, prepareTransactionalChange, getVersion, getChangesSince, getCurrentPollBaseline, getPollEmitter, canSeeChangeForUser, POLL_CHANGE_EVENT, } from "./poll.js";
@@ -41,7 +41,7 @@
41
41
  -Choose the primary workflow and route before editing. Add a domain route under `app/routes/` and set `app.homePath` in `server/plugins/agent-native-email-branding.ts` with `defineAppConfig`. The default Get started page lives at `/home`, and Chat stays at `/chat`; edit `app/routes/home.tsx` when replacing that page with a domain-specific home. Add a static link in `app/components/layout/Sidebar.tsx` before `ChatThreadsSection`; `Header.tsx` uses `APP_TITLE` elsewhere. Shared sidebar and AgentInspector remain.
42
42
  +Choose the primary workflow and route before editing. Build on the blank canvas in `app/routes/_index.tsx` or add domain routes under `app/routes/`. This starter has no Chat route, sidebar, header, or agent rail; add only the navigation the product needs. Set `app.homePath` in the existing `defineAppConfig` in `server/plugins/config.ts` as `DEVELOPING.md` describes.
43
43
 
44
- -Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow, including overlap rejection, cancellation freeing the slot, and authenticated landing. Skip production build and extra test suites.
44
+ -Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow and its authenticated landing. Skip production build and extra test suites.
45
45
  +Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here and update `README.md` as `DEVELOPING.md` describes. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow and its authenticated landing. Skip production build and extra test suites.
46
46
 
47
47
  Before building common workspace or agent UI, read `agent-native-toolkit`; for supported customization, read `customizing-agent-native`.
@@ -26,6 +26,6 @@ For custom branding, keep `server/plugins/agent-native-email-branding.ts` aligne
26
26
 
27
27
  Choose the primary workflow and route before editing. Add a domain route under `app/routes/` and set `app.homePath` in `server/plugins/agent-native-email-branding.ts` with `defineAppConfig`. The default Get started page lives at `/home`, and Chat stays at `/chat`; edit `app/routes/home.tsx` when replacing that page with a domain-specific home. Add a static link in `app/components/layout/Sidebar.tsx` before `ChatThreadsSection`; `Header.tsx` uses `APP_TITLE` elsewhere. Shared sidebar and AgentInspector remain.
28
28
 
29
- Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow, including overlap rejection, cancellation freeing the slot, and authenticated landing. Skip production build and extra test suites.
29
+ Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow and its authenticated landing. Skip production build and extra test suites.
30
30
 
31
31
  Before building common workspace or agent UI, read `agent-native-toolkit`; for supported customization, read `customizing-agent-native`.
@@ -3,6 +3,7 @@ import { defineAction } from "../../action.js";
3
3
  import { listAccessibleAutomationDefinitions, } from "../../automations/service.js";
4
4
  import { hasStalePause, isPausedByFramework, } from "../../jobs/automation-outcome.js";
5
5
  import { describeCron, effectiveTimezone, isValidCron, nextOccurrence, } from "../../jobs/cron.js";
6
+ import { isRecoveredFactoryJob, jobBelongsToApp, } from "../../jobs/frontmatter.js";
6
7
  import { listLatestAutomationRuns } from "../../jobs/run-history.js";
7
8
  function nextRun(meta) {
8
9
  if (!meta.enabled)
@@ -111,7 +112,12 @@ export default defineAction({
111
112
  deliveryTenantId: meta.deliveryTenantId ?? null,
112
113
  canUpdate,
113
114
  effectiveRole,
114
- capabilities,
115
+ capabilities: {
116
+ ...capabilities,
117
+ canOperate: capabilities.canOperate &&
118
+ (jobBelongsToApp(meta, ctx.appId) ||
119
+ isRecoveredFactoryJob(meta, resource.path, ctx.appId, resource.owner)),
120
+ },
115
121
  sharing,
116
122
  creator,
117
123
  };
@@ -17,7 +17,7 @@ The docs site is the reference implementation. Today it ships:
17
17
  - JSON-LD for base organization, website, and page metadata.
18
18
  - An audit CLI (`npx @agent-native/core@latest audit-agent-web`) that checks all of the above.
19
19
 
20
- Setting `publicMcp: true` additionally exposes opted-in actions as a public MCP endpoint, allowing external agents to call them directly (see [MCP Protocol](/docs/mcp-protocol)).
20
+ Publishing these files never exposes an action. An action reaches external agents only through its own `publicAgent` opt-in; see [Expose to public agents](/docs/actions-access-control#public-agent).
21
21
 
22
22
  <Diagram id="doc-block-1guzidr" title="What a public route publishes" summary={"A public route fans out into agent-friendly representations. Reading the route is separate from calling tools — tool access stays opt-in."}>
23
23
 
@@ -25,7 +25,7 @@ Setting `publicMcp: true` additionally exposes opted-in actions as a public MCP
25
25
  <div class="diagram-web">
26
26
  <div class="diagram-box" data-rough>
27
27
  Public route<br /><small class="diagram-muted"
28
- >derived from route access settings</small
28
+ >from the page list you pass</small
29
29
  >
30
30
  </div>
31
31
  <div class="diagram-arrow diagram-muted" aria-hidden="true">&rarr;</div>
@@ -40,9 +40,7 @@ Setting `publicMcp: true` additionally exposes opted-in actions as a public MCP
40
40
  <div class="diagram-arrow diagram-muted" aria-hidden="true">&rarr;</div>
41
41
  <div class="diagram-col gate">
42
42
  <span class="diagram-pill warn">Tools stay private</span
43
- ><small class="diagram-muted"
44
- >publicMcp + publicAgent.expose required</small
45
- >
43
+ ><small class="diagram-muted">publicAgent.expose required</small>
46
44
  </div>
47
45
  </div>
48
46
  ```
@@ -75,45 +73,57 @@ Setting `publicMcp: true` additionally exposes opted-in actions as a public MCP
75
73
 
76
74
  ## Configuration {#config}
77
75
 
78
- Add `agentWeb` under the existing workspace app config (in your app's `package.json` under the `agent-native` key — or equivalently `workspace.agentWeb`, `agentWeb`, or `root.agentWeb`). The public route list is still derived from the app's route access settings; `agentWeb` controls how that public surface is represented to agents.
79
-
80
- ```json
81
- {
82
- "agent-native": {
83
- "workspaceApp": {
84
- "audience": "public",
85
- "protectedPaths": ["/admin/*"],
86
- "agentWeb": {
87
- "discoverable": true,
88
- "markdownTwins": true,
89
- "llmsTxt": true,
90
- "jsonLd": true,
91
- "publicAgentCard": true,
92
- "publicMcp": false,
93
- "crawlerPolicy": "discoverable-no-training",
94
- "crawlers": {
95
- "training": "disallow",
96
- "search": "allow",
97
- "userTriggered": "allow",
98
- "codingAgents": "allow",
99
- "autonomousAgents": "allow"
100
- }
101
- }
102
- }
103
- }
104
- }
76
+ `createAgentWebVitePlugin` from `@agent-native/core/vite` writes these files during a production build. Add it to your Vite config with the pages agents should read:
77
+
78
+ ```ts
79
+ // vite.config.ts
80
+ import { defineConfig } from "vite";
81
+ import { createAgentWebVitePlugin } from "@agent-native/core/vite";
82
+
83
+ export default defineConfig({
84
+ plugins: [
85
+ // ...your existing plugins
86
+ createAgentWebVitePlugin({
87
+ siteName: "My Agent-Native App",
88
+ siteUrl: "https://example.com",
89
+ pages: [
90
+ {
91
+ path: "/pricing",
92
+ title: "Pricing",
93
+ description: "Plans and limits.",
94
+ markdown: "Plans and limits.\n",
95
+ },
96
+ ],
97
+ agentWeb: { crawlerPolicy: "discoverable-no-training" },
98
+ }),
99
+ ],
100
+ });
105
101
  ```
106
102
 
107
- For most apps, leave the defaults alone. If an app has any public route, `discoverable` defaults on. The default crawler policy is "discoverable, not trainable": search, user-triggered retrieval, coding agents, and autonomous browsing agents are allowed; training crawlers are disallowed.
103
+ The plugin publishes the pages you list and nothing else. It doesn't read your route access settings, and it doesn't read `agentWeb` from `package.json` unless you pass it in. To keep the settings in `package.json` under `agent-native.workspaceApp.agentWeb`, pass `agentWeb: agentWebConfigFromPackageJson(pkg)`, imported from `@agent-native/core/agent-web`.
104
+
105
+ | Option | Default | What it does |
106
+ | --------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
107
+ | `discoverable` | On when `pages` isn't empty | `false` writes no files. |
108
+ | `llmsTxt` | `true` | Writes `/llms.txt` and `/llms-full.txt`. |
109
+ | `markdownTwins` | `true` | Writes a `.md` copy of each page that has `markdown`. |
110
+ | `crawlerPolicy` | `"discoverable-no-training"` | Sets the `robots.txt` rules: `"discoverable-no-training"`, `"allow-all"`, or `"disallow-all"`. |
111
+ | `crawlers` | None | Overrides individual crawler categories: `training`, `search`, `userTriggered`, `codingAgents`, or `autonomousAgents`, each `"allow"` or `"disallow"`. |
112
+
113
+ The default crawler policy is "discoverable, not trainable": search, user-triggered retrieval, coding agents, and autonomous browsing agents are allowed; training crawlers are disallowed.
114
+
115
+ `jsonLd`, `publicAgentCard`, and `publicMcp` are accepted, but nothing reads them yet. For JSON-LD, render `buildBaseJsonLd` and `buildPageJsonLd` from `@agent-native/core/agent-web` into your pages yourself.
108
116
 
109
117
  ## Route source of truth {#route-source}
110
118
 
111
- Agent Web discovery follows the route access model:
119
+ The page list is the source of truth: agents get the pages you pass, and only those. Build it from pages that are already public:
120
+
121
+ - In a public app, every route except `protectedPaths`.
122
+ - In an internal app, only `publicPaths`.
123
+ - Public share and form pages that agents should be able to read.
124
+ - Never submitted private data, authenticated dashboards, or user or org state, even when a nearby page is public.
112
125
 
113
- - Public apps expose every route except `protectedPaths`.
114
- - Internal apps expose only `publicPaths`.
115
- - Public share and form pages can be readable by agents.
116
- - Submitted private data, authenticated dashboards, and user/org state are never included just because a nearby page is public.
126
+ To start from your access settings, `deriveAgentWebPublicRoutes` from `@agent-native/core/agent-web` takes your app's `audience`, `publicPaths`, `protectedPaths`, and `routes`, and returns the routes those settings make public. Each page still needs its own title and Markdown.
117
127
 
118
128
  This keeps mixed apps natural. A forms app can expose a public form page and keep submissions private. A content app can expose published posts and keep the editor private. A docs site can expose everything except admin tools.
119
129
 
@@ -123,7 +133,7 @@ Public page access and public tool access are separate. A route being public onl
123
133
 
124
134
  <Callout id="doc-block-s50w8y" tone="warning">
125
135
 
126
- **A public page is not a public tool.** Making a route crawlable never exposes an action. Tool access requires an explicit `publicAgent.expose` opt-in on the action _and_ `publicMcp: true` on the app.
136
+ **A public page is not a public tool.** Making a route crawlable never exposes an action. Tool access requires an explicit `publicAgent.expose` opt-in on the action.
127
137
 
128
138
  </Callout>
129
139
 
@@ -151,7 +161,7 @@ To expose an action through a public agent protocol, the action must opt in:
151
161
  ]}
152
162
  />
153
163
 
154
- `agentWeb.publicMcp` stays `false` by default. When public MCP is enabled, the server should expose only actions with `publicAgent.expose === true`, and should still exclude consequential or write actions unless the action and auth policy explicitly allow them.
164
+ No `agentWeb` setting exposes an action, and `publicMcp` has no effect today. See [Expose to public agents](/docs/actions-access-control#public-agent) for what `publicAgent` opts an action into and the checks that still apply.
155
165
 
156
166
  ## Build-time files {#build-time}
157
167
 
@@ -186,7 +196,9 @@ const files = buildAgentWebStaticFiles({
186
196
  });
187
197
  ```
188
198
 
189
- Vite apps can use `createAgentWebVitePlugin` from `@agent-native/core/vite` to write those files into `public`, `dist`, `dist/client`, `dist/server/public`, or `build/client` during production builds.
199
+ `createAgentWebVitePlugin` calls `buildAgentWebStaticFiles` for you and writes the files into whichever of `public`, `dist`, `dist/client`, `dist/server/public`, and `build/client` exist. With another build tool, call the utilities directly.
200
+
201
+ Neither one answers `Accept: text/markdown` on a page's own URL: the Markdown copy is only at its `.md` URL. To answer that header, add a server route that returns the page's Markdown with the headers from `buildMarkdownResponseHeaders`, as the docs site does. Without that route, the audit below fails its `Accept: text/markdown` check.
190
202
 
191
203
  Pass `sitemapGroup` to `buildAgentWebStaticFiles` or `createAgentWebVitePlugin` to split a large sitemap. It maps each page to a group key, such as its locale, and `sitemap.xml` becomes a sitemap index with one `sitemap-<group>.xml` per group.
192
204
 
@@ -215,5 +227,5 @@ The audit exits non-zero if a required public surface is missing.
215
227
  ## What's next
216
228
 
217
229
  - [**Actions**](/docs/actions-overview) — how to opt actions into the public agent protocol
218
- - [**MCP Protocol**](/docs/mcp-protocol) — the MCP surface that `publicMcp: true` enables
230
+ - [**MCP Protocol**](/docs/mcp-protocol) — the MCP server external agents connect to
219
231
  - [**Deployment**](/docs/deployment) — where these static files are written during builds
@@ -34,7 +34,7 @@ it. Use that name wherever a step below says APP_NAME.
34
34
  --standalone --template chat
35
35
  3. In the new APP_NAME folder, run `pnpm install`.
36
36
  4. Read APP_NAME/AGENTS.md so you know how the app is laid out.
37
- 5. Start the app with `pnpm dev` and keep it running in the background.
37
+ 5. Start the app with `pnpm dev --no-open` and keep it running in the background.
38
38
  6. Read the local URL that `pnpm dev` prints. Check that it responds,
39
39
  for example with `curl -I <url>`. Do not open a browser and do not
40
40
  use headless browser tools. I will open the app myself.
@@ -166,6 +166,14 @@ invalid document ID. Verify the link and connected account's access before
166
166
  changing permissions. Reinstalling the connector or changing the public share
167
167
  link does not resolve a confirmed account permission denial.
168
168
 
169
+ Images uploaded into a private document are stored in its body as
170
+ `/api/private-media/<id>` links, which load only with a Content sign-in.
171
+ When an agent reads the document over MCP, `get-document`, and `pull-document`
172
+ in Markdown, also return `privateMediaLinks`: each stored link paired with a
173
+ URL that opens that one image without signing in, for one hour. One read links
174
+ at most 200 images; `omitted` counts the rest. Read the document again for
175
+ fresh links. Keep the stored links when editing the body.
176
+
169
177
  <a id="access-tab"></a>
170
178
 
171
179
  ### The in-app MCP setting {#mcp-settings}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.227.0-nightly-20261110182415",
3
+ "version": "0.227.0",
4
4
  "description": "The agentic application framework for building autonomous agents with intuitive UIs",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -769,8 +769,8 @@
769
769
  "yaml": "^2.9.0",
770
770
  "yjs": "^13.6.33",
771
771
  "zod": "^4.3.6",
772
- "@agent-native/agentkit": "^0.227.0-nightly-20261110182415",
773
- "@agent-native/recap-cli": "^0.5.99"
772
+ "@agent-native/agentkit": "^0.227.0",
773
+ "@agent-native/recap-cli": "^0.5.100"
774
774
  },
775
775
  "devDependencies": {
776
776
  "@ai-sdk/anthropic": "^3.0.71",
@@ -843,7 +843,7 @@
843
843
  "xlsx": "^0.18.5"
844
844
  },
845
845
  "peerDependencies": {
846
- "@agent-native/core-corpus": "0.227.0-nightly-20261110182415",
846
+ "@agent-native/core-corpus": ">=0.196.0",
847
847
  "@ai-sdk/anthropic": ">=3",
848
848
  "@ai-sdk/cohere": ">=3",
849
849
  "@ai-sdk/google": ">=3",
@@ -41,7 +41,7 @@
41
41
  -Choose the primary workflow and route before editing. Add a domain route under `app/routes/` and set `app.homePath` in `server/plugins/agent-native-email-branding.ts` with `defineAppConfig`. The default Get started page lives at `/home`, and Chat stays at `/chat`; edit `app/routes/home.tsx` when replacing that page with a domain-specific home. Add a static link in `app/components/layout/Sidebar.tsx` before `ChatThreadsSection`; `Header.tsx` uses `APP_TITLE` elsewhere. Shared sidebar and AgentInspector remain.
42
42
  +Choose the primary workflow and route before editing. Build on the blank canvas in `app/routes/_index.tsx` or add domain routes under `app/routes/`. This starter has no Chat route, sidebar, header, or agent rail; add only the navigation the product needs. Set `app.homePath` in the existing `defineAppConfig` in `server/plugins/config.ts` as `DEVELOPING.md` describes.
43
43
 
44
- -Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow, including overlap rejection, cancellation freeing the slot, and authenticated landing. Skip production build and extra test suites.
44
+ -Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow and its authenticated landing. Skip production build and extra test suites.
45
45
  +Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here and update `README.md` as `DEVELOPING.md` describes. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow and its authenticated landing. Skip production build and extra test suites.
46
46
 
47
47
  Before building common workspace or agent UI, read `agent-native-toolkit`; for supported customization, read `customizing-agent-native`.
@@ -26,6 +26,6 @@ For custom branding, keep `server/plugins/agent-native-email-branding.ts` aligne
26
26
 
27
27
  Choose the primary workflow and route before editing. Add a domain route under `app/routes/` and set `app.homePath` in `server/plugins/agent-native-email-branding.ts` with `defineAppConfig`. The default Get started page lives at `/home`, and Chat stays at `/chat`; edit `app/routes/home.tsx` when replacing that page with a domain-specific home. Add a static link in `app/components/layout/Sidebar.tsx` before `ChatThreadsSection`; `Header.tsx` uses `APP_TITLE` elsewhere. Shared sidebar and AgentInspector remain.
28
28
 
29
- Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow, including overlap rejection, cancellation freeing the slot, and authenticated landing. Skip production build and extra test suites.
29
+ Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow and its authenticated landing. Skip production build and extra test suites.
30
30
 
31
31
  Before building common workspace or agent UI, read `agent-native-toolkit`; for supported customization, read `customizing-agent-native`.