@agent-native/core 0.210.0-nightly-20261019153056 → 0.210.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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/dist/agent/action-error-details.d.ts +26 -0
  3. package/dist/agent/action-error-details.js +99 -0
  4. package/dist/agent/execution-fence.d.ts +9 -2
  5. package/dist/agent/execution-fence.js +42 -12
  6. package/dist/agent/production-agent.js +9 -0
  7. package/dist/agent/run-manager.js +14 -14
  8. package/dist/agent/run-store.js +8 -6
  9. package/dist/agent/tool-error-redaction.d.ts +8 -1
  10. package/dist/agent/tool-error-redaction.js +70 -7
  11. package/dist/collab/awareness.d.ts +2 -2
  12. package/dist/collab/routes.d.ts +1 -1
  13. package/dist/collab/struct-routes.d.ts +1 -1
  14. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  15. package/dist/mcp/actions/create-org-service-token.js +6 -3
  16. package/dist/mcp/actions/set-service-principal-lifecycle.js +1 -0
  17. package/dist/mcp/actions/set-service-principal-policy.js +1 -0
  18. package/dist/mcp/direct-action-call.js +39 -10
  19. package/dist/notifications/routes.d.ts +3 -3
  20. package/dist/observability/routes.d.ts +3 -3
  21. package/dist/onboarding/workspace-services.js +1 -1
  22. package/dist/progress/routes.d.ts +1 -1
  23. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  24. package/dist/secrets/routes.d.ts +6 -6
  25. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  26. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  27. package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
  28. package/dist/templates/chat/.agents/skills/actions/SKILL.md +2 -2
  29. package/dist/templates/chat/netlify.toml +0 -1
  30. package/dist/templates/default/.agents/skills/actions/SKILL.md +2 -2
  31. package/dist/templates/factory/.agents/skills/review-prs/SKILL.md +44 -21
  32. package/dist/templates/headless/.agents/skills/actions/SKILL.md +2 -2
  33. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +2 -2
  34. package/docs/content/actions-defining.mdx +2 -2
  35. package/docs/content/template-chat-agent.mdx +88 -0
  36. package/docs/content/template-chat-developers.mdx +586 -104
  37. package/docs/content/template-chat-features.mdx +158 -0
  38. package/docs/content/template-chat-integrations.mdx +66 -0
  39. package/docs/content/template-chat.mdx +36 -166
  40. package/docs/content/template-clips-developers.mdx +1 -1
  41. package/docs/content/template-clips-integrations.mdx +50 -5
  42. package/package.json +4 -4
  43. package/src/templates/chat/.agents/skills/actions/SKILL.md +2 -2
  44. package/src/templates/chat/netlify.toml +0 -1
  45. package/src/templates/default/.agents/skills/actions/SKILL.md +2 -2
  46. package/src/templates/factory/.agents/skills/review-prs/SKILL.md +44 -21
  47. package/src/templates/headless/.agents/skills/actions/SKILL.md +2 -2
  48. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +2 -2
  49. package/docs/content/template-chat-first-edits.mdx +0 -158
@@ -1,5 +1,6 @@
1
1
  import { actionCallReadOnly, actionChangeResource, } from "../action-call-classification.js";
2
2
  import { ActionOutputContractError, failedCallEmitsChange, isActionOutputContractError, invocationEffect, ranCallEmitsChange, } from "../action.js";
3
+ import { agentErrorDetails } from "../agent/action-error-details.js";
3
4
  import { extractAgentImagesFromActionResult } from "../agent/tool-result-images.js";
4
5
  import { writeActionChangeMarker } from "../server/action-change-marker-write.js";
5
6
  import { captureError } from "../server/capture-error.js";
@@ -35,6 +36,13 @@ export function createDirectActionCall(scope) {
35
36
  return async (call, fail) => {
36
37
  const { name, args, request, ctx } = call;
37
38
  const callableActions = fullCatalogRequested ? actions : advertisedActions;
39
+ // A directory profile may project results arbitrarily, so the derived
40
+ // contract is advertised and enforced on app catalogs only. It compiles
41
+ // before the action runs. A host may hold an error result to the same
42
+ // schema, so a contracted tool's errors carry no structuredContent.
43
+ const outputContract = directoryCatalog
44
+ ? undefined
45
+ : callableActions[name]?.mcpOutputContract;
38
46
  const errorText = (err) => {
39
47
  const projectedError = directoryCatalog && config.directoryProfile?.projectResult
40
48
  ? config.directoryProfile.projectResult(name, err.message)
@@ -55,10 +63,37 @@ export function createDirectActionCall(scope) {
55
63
  try {
56
64
  const errorCode = mcpActionErrorCode(err);
57
65
  const { errorType, errorMessage } = describeMcpError(err);
58
- return toolCallError({
59
- errorType: redactEmbedText(errorType),
60
- errorMessage: redactEmbedText(errorMessage),
61
- }, `${redactEmbedText(errorText(err))}${errorCode !== undefined ? ` (errorCode: ${redactEmbedText(errorCode)})` : ""}`);
66
+ const message = redactEmbedText(errorText(err));
67
+ // A directory profile decides what its catalog shows, and it
68
+ // projects only the message.
69
+ const details = directoryCatalog ? undefined : agentErrorDetails(err);
70
+ const detailsLine = details && redactEmbedText(details.line);
71
+ return {
72
+ ...toolCallError({
73
+ errorType: redactEmbedText(errorType),
74
+ errorMessage: redactEmbedText(errorMessage),
75
+ }, `${message}${errorCode !== undefined ? ` (errorCode: ${redactEmbedText(errorCode)})` : ""}${detailsLine ? `\n${detailsLine}` : ""}`),
76
+ // Some clients hand the model structuredContent in place of the
77
+ // text, so it repeats the message rather than carrying details
78
+ // alone. Details the embed check hid in the text stay out of it.
79
+ ...(details && detailsLine === details.line && !outputContract
80
+ ? {
81
+ structuredContent: {
82
+ error: {
83
+ message,
84
+ errorCode: err.errorCode,
85
+ details: details.details,
86
+ ...(details.omittedKeys
87
+ ? {
88
+ omittedKeys: details.omittedKeys,
89
+ omittedKeyCount: details.omittedKeyCount,
90
+ }
91
+ : {}),
92
+ },
93
+ },
94
+ }
95
+ : {}),
96
+ };
62
97
  }
63
98
  catch {
64
99
  return toolCallError({
@@ -67,12 +102,6 @@ export function createDirectActionCall(scope) {
67
102
  });
68
103
  }
69
104
  };
70
- // A directory profile may project results arbitrarily, so the derived
71
- // contract is advertised and enforced on app catalogs only. It compiles
72
- // before the action runs.
73
- const outputContract = directoryCatalog
74
- ? undefined
75
- : callableActions[name]?.mcpOutputContract;
76
105
  let checkOutput;
77
106
  try {
78
107
  checkOutput = outputContract
@@ -1,12 +1,12 @@
1
1
  export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
2
+ error?: undefined;
2
3
  count: number;
3
4
  updated?: undefined;
4
- error?: undefined;
5
5
  ok?: undefined;
6
6
  } | {
7
+ error?: undefined;
7
8
  count?: undefined;
8
9
  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;
17
18
  count?: undefined;
18
19
  updated?: undefined;
19
- error?: undefined;
20
20
  ok: boolean;
21
21
  }>>;
@@ -33,22 +33,22 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
33
33
  summary?: undefined;
34
34
  spans?: undefined;
35
35
  } | {
36
- ok?: undefined;
37
36
  error?: undefined;
37
+ ok?: undefined;
38
38
  message?: undefined;
39
39
  summary: import("./types.js").TraceSummary;
40
40
  spans: import("./types.js").TraceSpan[];
41
41
  } | {
42
- ok?: undefined;
43
42
  error?: undefined;
43
+ ok?: undefined;
44
44
  message?: undefined;
45
45
  summary?: undefined;
46
46
  spans?: undefined;
47
47
  traceMissing: true;
48
48
  id: string;
49
49
  } | {
50
- ok?: undefined;
51
50
  error?: undefined;
51
+ ok?: undefined;
52
52
  message?: undefined;
53
53
  summary?: undefined;
54
54
  spans?: undefined;
@@ -103,7 +103,7 @@ export const WEB_SEARCH_CAPABILITY = {
103
103
  required: false,
104
104
  suggested: true,
105
105
  builderIncluded: true,
106
- keySummary: "Builder-managed web search",
106
+ keySummary: "Web search",
107
107
  labelKey: "agentChat.onboarding.capability.webSearch.label",
108
108
  keySummaryKey: "agentChat.onboarding.capability.webSearch.keySummary",
109
109
  whyKey: "agentChat.onboarding.capability.webSearch.why",
@@ -2,6 +2,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
2
2
  error: string;
3
3
  ok?: undefined;
4
4
  } | {
5
- ok: boolean;
6
5
  error?: undefined;
6
+ ok: boolean;
7
7
  }>>;
@@ -75,6 +75,7 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
75
75
  user: "user";
76
76
  }>>;
77
77
  }, z.core.$strip>>, {
78
+ message?: undefined;
78
79
  deleted?: undefined;
79
80
  found?: undefined;
80
81
  id?: undefined;
@@ -91,8 +92,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
91
92
  provider?: undefined;
92
93
  registered?: undefined;
93
94
  label?: undefined;
94
- message?: undefined;
95
95
  } | {
96
+ message?: undefined;
96
97
  deleted?: undefined;
97
98
  id?: undefined;
98
99
  providers?: undefined;
@@ -101,8 +102,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
101
102
  provider: import("../custom-registry.js").CustomProviderConfig;
102
103
  registered?: undefined;
103
104
  label?: undefined;
104
- message?: undefined;
105
105
  } | {
106
+ message?: undefined;
106
107
  deleted?: undefined;
107
108
  providers?: undefined;
108
109
  count?: undefined;
@@ -111,8 +112,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
111
112
  id: string;
112
113
  registered?: undefined;
113
114
  label?: undefined;
114
- message?: undefined;
115
115
  } | {
116
+ message?: undefined;
116
117
  found?: undefined;
117
118
  providers?: undefined;
118
119
  count?: undefined;
@@ -121,7 +122,6 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
121
122
  id: string;
122
123
  registered?: undefined;
123
124
  label?: undefined;
124
- message?: undefined;
125
125
  } | {
126
126
  deleted?: undefined;
127
127
  found?: undefined;
@@ -65,31 +65,31 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
65
65
  ok?: undefined;
66
66
  status?: undefined;
67
67
  } | {
68
+ error?: undefined;
68
69
  errorCode?: undefined;
69
70
  ok: boolean;
70
71
  status: string;
71
- error?: undefined;
72
72
  } | {
73
73
  ok?: undefined;
74
74
  error: string;
75
75
  removed?: undefined;
76
76
  } | {
77
+ error?: undefined;
77
78
  ok: boolean;
78
79
  removed: boolean;
79
- error?: undefined;
80
80
  }>>;
81
81
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
82
82
  ok?: undefined;
83
83
  error: string;
84
84
  note?: undefined;
85
85
  } | {
86
+ error?: undefined;
86
87
  ok: boolean;
87
88
  note?: undefined;
88
- error?: undefined;
89
89
  } | {
90
+ error?: undefined;
90
91
  ok: boolean;
91
92
  note: string;
92
- error?: undefined;
93
93
  } | {
94
94
  note?: undefined;
95
95
  ok: boolean;
@@ -117,11 +117,11 @@ export declare function createAdHocSecretHandler(): import("h3").EventHandlerWit
117
117
  } | {
118
118
  error: string;
119
119
  } | {
120
+ error?: undefined;
120
121
  ok: boolean;
121
122
  key: string;
122
- error?: undefined;
123
123
  } | {
124
+ error?: undefined;
124
125
  ok: boolean;
125
126
  removed: boolean;
126
- error?: undefined;
127
127
  }>>;
@@ -66,8 +66,8 @@ export declare function createAgentEngineApiKeyHandler(): import("h3").EventHand
66
66
  error: any;
67
67
  code: any;
68
68
  } | {
69
- errorCode?: undefined;
70
69
  error?: undefined;
70
+ errorCode?: undefined;
71
71
  code?: undefined;
72
72
  ok: boolean;
73
73
  key: string;
@@ -8,8 +8,8 @@ export declare const AGENT_ENGINE_API_KEY_ACTION_NAME = "agent-engine-api-key";
8
8
  * resolveEngine's credential detection.
9
9
  */
10
10
  export declare function createAgentEngineDisconnectHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
11
- ok?: undefined;
12
11
  error: string;
12
+ ok?: undefined;
13
13
  scope?: undefined;
14
14
  } | {
15
15
  ok: boolean;
@@ -1,9 +1,9 @@
1
1
  export declare function createAgentEngineOllamaModelsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
2
2
  error: string;
3
- models?: undefined;
4
3
  ok?: undefined;
4
+ models?: undefined;
5
5
  } | {
6
+ error?: undefined;
6
7
  ok: boolean;
7
8
  models: string[];
8
- error?: undefined;
9
9
  }>>;
@@ -170,10 +170,10 @@ Everything else — CRUD, settings, search, list/detail reads, auth state, anyth
170
170
  - **Do** keep one action, one job; document a reusable action (when to use it, key args, return fields to preserve) in `AGENTS.md` once it's called from outside one narrow screen; promote workflow-heavy actions (provider-backed, cross-app, MCP/A2A, multi-step) into a skill.
171
171
  - **Do** use `fail(message, { errorCode, statusCode })` for user-friendly errors and import primitives from `@agent-native/core`(`/action`) instead of redefining them; use the core `upload-image` action or `uploadFile()` for durable images/files — never base64 into SQL, markdown, or action results.
172
172
  - **Do** signal failure by throwing, using `fail()` for expected caller-readable failures. Never return `{ error: ... }` as a failure result: a normal return is treated as a successful action. Reserve bare errors for unexpected internal faults.
173
- - **Do** use `fail()` rather than a bare `Error` for caller-readable failures. It carries the action's message, `errorCode`, and `details` to the browser; unexpected errors become a generic 500. Reserve bare throws for internal faults.
173
+ - **Do** use `fail()` rather than a bare `Error` for caller-readable failures. It carries the action's message, `errorCode`, and `details` to the browser and to agents; unexpected errors become a generic 500. Reserve bare throws for internal faults.
174
174
  - **Do** give `fail()` the status that matches the cause: it defaults to `400`, and `useActionQuery` retries only `429`, `502`, `503`, and `504`. Mutations do not retry; use transient statuses only for retryable failures.
175
175
  - **Do** render `actionErrorMessage(error) ?? yourCopy` in UI, never bare `error.message`. The message keeps an `Action <name> failed:` prefix that belongs in a console, so a toast built from it reads "Action update-brand-kit failed: That name is taken." The helper returns only what the action wrote, and `undefined` when nothing did (network drop, proxy HTML page), which is why the fallback is not optional.
176
- - **Do** pass a real `errorCode` when the agent should branch on the failure rather than re-read it. Codes other than the default `action_failed` are appended to the tool result as `(errorCode: not_found)`, on both the in-app agent and MCP; `details` and the status never reach either.
176
+ - **Do** pass a real `errorCode` when the agent should branch on the failure rather than re-read it. Codes other than the default `action_failed` are appended to the tool result as `(errorCode: not_found)`, on both the in-app agent and MCP. `details` follow as an `Error details: {...}` JSON line, and as `structuredContent.error` over MCP, capped at 2,000 characters, so keep them to what the agent acts on next: ids, limits, field names. The status never reaches either.
177
177
  - **Don't** re-export actions as REST — `/_agent-native/actions/:name` is already the REST surface; duplicating it under `/api/*` hides the operation from agents.
178
178
  - **Don't** reach for provider integrations, `outputSchema`, `authorize`, `needsApproval`, or `_agentImages` without checking `references/` first — each has sharp edges covered there, not here.
179
179
 
@@ -12,7 +12,6 @@ NPM_CONFIG_PRODUCTION = "false"
12
12
 
13
13
  [context.production.environment]
14
14
  AGENT_NATIVE_HOSTED_HARNESS = "true"
15
- AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
16
15
  AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
17
16
  BETTER_AUTH_TRUSTED_ORIGINS = "https://starter.agent-native.com,https://chat.agent-native.com"
18
17
  # Production release migrations own schema setup; request functions must skip
@@ -170,10 +170,10 @@ Everything else — CRUD, settings, search, list/detail reads, auth state, anyth
170
170
  - **Do** keep one action, one job; document a reusable action (when to use it, key args, return fields to preserve) in `AGENTS.md` once it's called from outside one narrow screen; promote workflow-heavy actions (provider-backed, cross-app, MCP/A2A, multi-step) into a skill.
171
171
  - **Do** use `fail(message, { errorCode, statusCode })` for user-friendly errors and import primitives from `@agent-native/core`(`/action`) instead of redefining them; use the core `upload-image` action or `uploadFile()` for durable images/files — never base64 into SQL, markdown, or action results.
172
172
  - **Do** signal failure by throwing, using `fail()` for expected caller-readable failures. Never return `{ error: ... }` as a failure result: a normal return is treated as a successful action. Reserve bare errors for unexpected internal faults.
173
- - **Do** use `fail()` rather than a bare `Error` for caller-readable failures. It carries the action's message, `errorCode`, and `details` to the browser; unexpected errors become a generic 500. Reserve bare throws for internal faults.
173
+ - **Do** use `fail()` rather than a bare `Error` for caller-readable failures. It carries the action's message, `errorCode`, and `details` to the browser and to agents; unexpected errors become a generic 500. Reserve bare throws for internal faults.
174
174
  - **Do** give `fail()` the status that matches the cause: it defaults to `400`, and `useActionQuery` retries only `429`, `502`, `503`, and `504`. Mutations do not retry; use transient statuses only for retryable failures.
175
175
  - **Do** render `actionErrorMessage(error) ?? yourCopy` in UI, never bare `error.message`. The message keeps an `Action <name> failed:` prefix that belongs in a console, so a toast built from it reads "Action update-brand-kit failed: That name is taken." The helper returns only what the action wrote, and `undefined` when nothing did (network drop, proxy HTML page), which is why the fallback is not optional.
176
- - **Do** pass a real `errorCode` when the agent should branch on the failure rather than re-read it. Codes other than the default `action_failed` are appended to the tool result as `(errorCode: not_found)`, on both the in-app agent and MCP; `details` and the status never reach either.
176
+ - **Do** pass a real `errorCode` when the agent should branch on the failure rather than re-read it. Codes other than the default `action_failed` are appended to the tool result as `(errorCode: not_found)`, on both the in-app agent and MCP. `details` follow as an `Error details: {...}` JSON line, and as `structuredContent.error` over MCP, capped at 2,000 characters, so keep them to what the agent acts on next: ids, limits, field names. The status never reaches either.
177
177
  - **Don't** re-export actions as REST — `/_agent-native/actions/:name` is already the REST surface; duplicating it under `/api/*` hides the operation from agents.
178
178
  - **Don't** reach for provider integrations, `outputSchema`, `authorize`, `needsApproval`, or `_agentImages` without checking `references/` first — each has sharp edges covered there, not here.
179
179
 
@@ -3,8 +3,9 @@ name: review-prs
3
3
  description: >-
4
4
  Review recent BuilderIO/agent-native human pull requests, approve eligible
5
5
  internal PRs, and merge changes that are ready by Steve's bar. Use for
6
- scheduled or manual PR sweeps; flag external non-bug work and unresolved major
7
- product or UX decisions to Steve.
6
+ scheduled or manual PR sweeps; flag external work needing a major product
7
+ call or new framework API, and unresolved major product or UX decisions, to
8
+ Steve.
8
9
  user-invocable: true
9
10
  scope: dev
10
11
  metadata:
@@ -20,10 +21,12 @@ approve an external or unverified author.
20
21
 
21
22
  Approval and merge readiness are separate. A **Ready to merge by Steve's bar**
22
23
  result means merge the PR under the guarded merge procedure below. For a
23
- confirmed external author, only a clear bug fix enters evidence review and the
24
- possible merge flow; external authors are never eligible for an approval
25
- review. Surface other external work for Steve's explicit approval before a full
26
- review or merge; a scheduled or manual sweep is not that approval.
24
+ confirmed external author, a clear bug fix or a bounded improvement that
25
+ follows existing patterns enters evidence review and the possible merge flow;
26
+ external authors are never eligible for an approval review. Surface external
27
+ work that needs a major product call or a new framework API for Steve's explicit
28
+ approval before a full review or merge; a scheduled or manual sweep is not that
29
+ approval.
27
30
 
28
31
  ## Selection and evidence
29
32
 
@@ -53,6 +56,11 @@ author and draft state:
53
56
  summary to determine whether the PR already has a current, non-dismissed
54
57
  `APPROVED` review.
55
58
 
59
+ - Before the scope gate, check a confirmed nonmember's PR from a fork for
60
+ assignees. If any assignee is a verified current BuilderIO member, ignore
61
+ the PR completely, like a draft: that person owns it under `community-prs`.
62
+ Take no review, reply, or merge action, and leave it out of the recap.
63
+
56
64
  - Reuse that review as the code assessment only after verifying the reviewer
57
65
  is a different, current BuilderIO member and is eligible under the PR's
58
66
  author- and scope-specific rules, including any independent-review
@@ -99,17 +107,28 @@ the patch looks safe or the issue is obviously valid.
99
107
 
100
108
  ## External-contribution scope gate
101
109
 
110
+ Builder devs decide bounded outside contributions; Steve keeps major product
111
+ calls and new framework APIs.
112
+
102
113
  For an author the membership API confirms is not a current BuilderIO member,
103
- continue into the normal evidence sweep only for a clear bug fix: a change that
104
- corrects a specific reported or reproducible defect by restoring intended
105
- behavior. A feature, improvement, refactor, new or changed product behavior, or
106
- mixed bug-fix-and-enhancement scope is not a clear bug fix. If the title, issue,
107
- and initial diff do not establish a clear bug fix, treat it as non-bug work.
108
-
109
- For external non-bug work, stop before the full code review, approval or review
110
- action, merge-readiness disposition, author-facing draft, or merge. Report it to
111
- Steve as **Needs Steve's approval for scope**, with the PR link, author, stated
112
- scope, and why it is not a clear bug fix. Wait for Steve's explicit go-ahead on
114
+ continue into the normal evidence sweep for a clear bug fix or a bounded
115
+ improvement. A clear bug fix corrects a specific reported or reproducible
116
+ defect by restoring intended behavior. A bounded improvement stays within one
117
+ established workflow, app, or framework area and follows the patterns already
118
+ there.
119
+
120
+ External work needs Steve when it makes a major product call (as defined under
121
+ Product and UX decisions) or adds a new framework API: a new public export,
122
+ configuration option, action, plugin or hook contract, or CLI surface in a
123
+ published package under `packages/`. A fix or bounded improvement to an existing
124
+ API stays with devs when it keeps that API's contract. If the title, issue, and
125
+ initial diff do not establish a clear bug fix or a bounded improvement, treat it
126
+ as needing Steve.
127
+
128
+ For external work that needs Steve, stop before the full code review, approval
129
+ or review action, merge-readiness disposition, author-facing draft, or merge.
130
+ Report it to Steve as **Needs Steve's approval for scope**, with the PR link,
131
+ author, stated scope, and which call it needs. Wait for Steve's explicit go-ahead on
113
132
  that PR before continuing. Invoking or scheduling `review-prs`, approving a
114
133
  different PR, or prior approval of another external contribution does not
115
134
  authorize it. If membership is unknown, use the existing unknown-membership
@@ -118,6 +137,8 @@ solely because membership could not be verified. Keep the no-approval outcome,
118
137
  report the missing membership check, and assess merge readiness under the
119
138
  existing unknown-membership policy.
120
139
 
140
+ Builder devs own outside PRs end to end with `community-prs`.
141
+
121
142
  ## Liamdebeasi approval policy
122
143
 
123
144
  For a PR authored by the exact GitHub login `liamdebeasi` and immutable user
@@ -296,9 +317,10 @@ merge scope and must remain completely untouched.
296
317
  For a PR that fails an approval gate, do not submit an approval. Flag the exact
297
318
  concern and the evidence needed to resolve it. External or unverified authors
298
319
  never receive an approval review, but their PRs can still be merged when they
299
- meet the readiness gate below. Confirmed external bug fixes must also pass the
300
- external-contribution scope gate; confirmed external non-bug work remains
301
- stopped at Steve's approval gate. For unknown membership, do not apply the
320
+ meet the readiness gate below. Confirmed external PRs must also pass the
321
+ external-contribution scope gate; external work that needs a major product call
322
+ or a new framework API remains stopped at Steve's approval gate. For unknown
323
+ membership, do not apply the
302
324
  external scope gate solely because verification failed; preserve the
303
325
  no-approval outcome, assess readiness under the existing unknown-membership
304
326
  policy, and name the missing check.
@@ -504,7 +526,8 @@ non-auto-approved external PR that needs an update or screenshot, include its
504
526
  draft reply in a separate section, or mark it waiting on the contributor with
505
527
  a link to Steve's outstanding request. For internal PRs, report the needed
506
528
  update or screenshot without drafting an author-facing reply. Do not add rows
507
- for bots, `steve8708`, or drafts; those are ignored completely.
529
+ for bots, `steve8708`, drafts, or external PRs assigned to a BuilderIO member;
530
+ those are ignored completely.
508
531
 
509
532
  Use this shape:
510
533
 
@@ -525,4 +548,4 @@ blocker when the PR is ready and the guarded admin merge is available.
525
548
 
526
549
  ## Related skills
527
550
 
528
- `concurrent-agents`, `verifying-changes`, `ship`, `babysit-pr`
551
+ `concurrent-agents`, `verifying-changes`, `ship`, `babysit-pr`, `community-prs`
@@ -170,10 +170,10 @@ Everything else — CRUD, settings, search, list/detail reads, auth state, anyth
170
170
  - **Do** keep one action, one job; document a reusable action (when to use it, key args, return fields to preserve) in `AGENTS.md` once it's called from outside one narrow screen; promote workflow-heavy actions (provider-backed, cross-app, MCP/A2A, multi-step) into a skill.
171
171
  - **Do** use `fail(message, { errorCode, statusCode })` for user-friendly errors and import primitives from `@agent-native/core`(`/action`) instead of redefining them; use the core `upload-image` action or `uploadFile()` for durable images/files — never base64 into SQL, markdown, or action results.
172
172
  - **Do** signal failure by throwing, using `fail()` for expected caller-readable failures. Never return `{ error: ... }` as a failure result: a normal return is treated as a successful action. Reserve bare errors for unexpected internal faults.
173
- - **Do** use `fail()` rather than a bare `Error` for caller-readable failures. It carries the action's message, `errorCode`, and `details` to the browser; unexpected errors become a generic 500. Reserve bare throws for internal faults.
173
+ - **Do** use `fail()` rather than a bare `Error` for caller-readable failures. It carries the action's message, `errorCode`, and `details` to the browser and to agents; unexpected errors become a generic 500. Reserve bare throws for internal faults.
174
174
  - **Do** give `fail()` the status that matches the cause: it defaults to `400`, and `useActionQuery` retries only `429`, `502`, `503`, and `504`. Mutations do not retry; use transient statuses only for retryable failures.
175
175
  - **Do** render `actionErrorMessage(error) ?? yourCopy` in UI, never bare `error.message`. The message keeps an `Action <name> failed:` prefix that belongs in a console, so a toast built from it reads "Action update-brand-kit failed: That name is taken." The helper returns only what the action wrote, and `undefined` when nothing did (network drop, proxy HTML page), which is why the fallback is not optional.
176
- - **Do** pass a real `errorCode` when the agent should branch on the failure rather than re-read it. Codes other than the default `action_failed` are appended to the tool result as `(errorCode: not_found)`, on both the in-app agent and MCP; `details` and the status never reach either.
176
+ - **Do** pass a real `errorCode` when the agent should branch on the failure rather than re-read it. Codes other than the default `action_failed` are appended to the tool result as `(errorCode: not_found)`, on both the in-app agent and MCP. `details` follow as an `Error details: {...}` JSON line, and as `structuredContent.error` over MCP, capped at 2,000 characters, so keep them to what the agent acts on next: ids, limits, field names. The status never reaches either.
177
177
  - **Don't** re-export actions as REST — `/_agent-native/actions/:name` is already the REST surface; duplicating it under `/api/*` hides the operation from agents.
178
178
  - **Don't** reach for provider integrations, `outputSchema`, `authorize`, `needsApproval`, or `_agentImages` without checking `references/` first — each has sharp edges covered there, not here.
179
179
 
@@ -170,10 +170,10 @@ Everything else — CRUD, settings, search, list/detail reads, auth state, anyth
170
170
  - **Do** keep one action, one job; document a reusable action (when to use it, key args, return fields to preserve) in `AGENTS.md` once it's called from outside one narrow screen; promote workflow-heavy actions (provider-backed, cross-app, MCP/A2A, multi-step) into a skill.
171
171
  - **Do** use `fail(message, { errorCode, statusCode })` for user-friendly errors and import primitives from `@agent-native/core`(`/action`) instead of redefining them; use the core `upload-image` action or `uploadFile()` for durable images/files — never base64 into SQL, markdown, or action results.
172
172
  - **Do** signal failure by throwing, using `fail()` for expected caller-readable failures. Never return `{ error: ... }` as a failure result: a normal return is treated as a successful action. Reserve bare errors for unexpected internal faults.
173
- - **Do** use `fail()` rather than a bare `Error` for caller-readable failures. It carries the action's message, `errorCode`, and `details` to the browser; unexpected errors become a generic 500. Reserve bare throws for internal faults.
173
+ - **Do** use `fail()` rather than a bare `Error` for caller-readable failures. It carries the action's message, `errorCode`, and `details` to the browser and to agents; unexpected errors become a generic 500. Reserve bare throws for internal faults.
174
174
  - **Do** give `fail()` the status that matches the cause: it defaults to `400`, and `useActionQuery` retries only `429`, `502`, `503`, and `504`. Mutations do not retry; use transient statuses only for retryable failures.
175
175
  - **Do** render `actionErrorMessage(error) ?? yourCopy` in UI, never bare `error.message`. The message keeps an `Action <name> failed:` prefix that belongs in a console, so a toast built from it reads "Action update-brand-kit failed: That name is taken." The helper returns only what the action wrote, and `undefined` when nothing did (network drop, proxy HTML page), which is why the fallback is not optional.
176
- - **Do** pass a real `errorCode` when the agent should branch on the failure rather than re-read it. Codes other than the default `action_failed` are appended to the tool result as `(errorCode: not_found)`, on both the in-app agent and MCP; `details` and the status never reach either.
176
+ - **Do** pass a real `errorCode` when the agent should branch on the failure rather than re-read it. Codes other than the default `action_failed` are appended to the tool result as `(errorCode: not_found)`, on both the in-app agent and MCP. `details` follow as an `Error details: {...}` JSON line, and as `structuredContent.error` over MCP, capped at 2,000 characters, so keep them to what the agent acts on next: ids, limits, field names. The status never reaches either.
177
177
  - **Don't** re-export actions as REST — `/_agent-native/actions/:name` is already the REST surface; duplicating it under `/api/*` hides the operation from agents.
178
178
  - **Don't** reach for provider integrations, `outputSchema`, `authorize`, `needsApproval`, or `_agentImages` without checking `references/` first — each has sharp edges covered there, not here.
179
179
 
@@ -324,7 +324,7 @@ What you throw decides how much of the message survives. `fail()` raises an `Act
324
324
  - **message**: the text the caller reads. Write it for a person, not for a log.
325
325
  - **options.errorCode**: a stable machine-readable code. Defaults to `"action_failed"`.
326
326
  - **options.statusCode**: the HTTP status for the action route. Defaults to `400`.
327
- - **options.details**: safe structured context for the caller. Never put secrets or raw driver output here.
327
+ - **options.details**: safe structured context for the caller, such as the id a retry needs. The browser and agents both receive it. Never put secrets or raw driver output here.
328
328
 
329
329
  The simplest call needs only a message:
330
330
 
@@ -402,7 +402,7 @@ A network drop, a proxy's HTML error page, and a bare status line author no mess
402
402
 
403
403
  So the status is not cosmetic. A refusal sent as `404` costs one round trip. The same refusal sent as a `500`, or thrown bare, costs four round trips and four duplicate error reports.
404
404
 
405
- Agent callers never see the status. The agent runs `run()` in process, so it receives the message directly whatever the type, as `Error running <action>: <message>`. An `errorCode` other than the default `action_failed` is appended as `(errorCode: not_found)` so the model can branch on it without parsing prose. External agents over MCP get the same text. Secrets in the message are redacted first, and the agent's own repeated-error breakers bound how many times it tries again.
405
+ Agent callers never see the status. The agent runs `run()` in process, so it receives the message directly whatever the type, as `Error running <action>: <message>`. An `errorCode` other than the default `action_failed` is appended as `(errorCode: not_found)` so the model can branch on it without parsing prose. `details` follow on their own line as compact JSON, such as `Error details: {"importId":"imp_1"}`, so an id the model needs for its next call doesn't have to be written into the message. External agents over MCP get the same text, and the same details in `structuredContent.error`. A tool that advertises an output schema (`mcpOutputSchema: true`) returns the text only, since a client may check an error result against that schema too. Details are capped at 2,000 characters: past that, small top-level entries are kept and the rest are listed as omitted. Secrets in the message and details are redacted first, and the agent's own repeated-error breakers bound how many times it tries again.
406
406
 
407
407
  ## Keep the action surface small {#small-surface}
408
408
 
@@ -0,0 +1,88 @@
1
+ ---
2
+ title: "Chat: Talk to the Agent"
3
+ description: "What the agent knows about where you are in Chat, and prompts organized by task."
4
+ ---
5
+
6
+ # Talk to the Agent
7
+
8
+ In Chat, the conversation is the main way you use the app. The agent can run the app's actions, look things up, remember what you tell it, and take you to other pages. This page covers what the agent knows about your screen, useful prompts by task, and where it goes beyond the built-in actions. See [Chat](/docs/template-chat) for the overview.
9
+
10
+ ## How the agent sees your screen
11
+
12
+ The agent always knows which page you're on and which conversation is open. That's why "take me back to Home" or "what page am I on?" works without any explanation. The app tells the agent about every page change as it happens, so the agent never has to guess.
13
+
14
+ Chat has no business data to point at, such as a selected event or an open document. Everything else the agent knows comes from what you say in the conversation.
15
+
16
+ ## Useful prompts by task
17
+
18
+ Every prompt below runs against the real app. Here's one worked example:
19
+
20
+ <Comparison>
21
+
22
+ ### :blue: You ask
23
+
24
+ "Call the hello action for Alex."
25
+
26
+ ### :green: What happens
27
+
28
+ The agent runs the example **hello** action with the name Alex. The action
29
+ returns "Hello, Alex!" and the agent shows it in the chat. Nothing else in the
30
+ app changes.
31
+
32
+ </Comparison>
33
+
34
+ <Cards columns={2}>
35
+
36
+ ### Learn what the app can do
37
+
38
+ - **"What can this app do?"** The agent lists the actions it has and what each
39
+ one does.
40
+ - **"Show me the available actions."** Same idea, as a plain list of names.
41
+ - **"Help me get started."** The agent suggests a first thing to try.
42
+
43
+ ### Get around
44
+
45
+ - **"Take me to Settings."** The app opens the page for you.
46
+ - **"Open the Database page."** The agent opens `/database`, which isn't linked
47
+ from the sidebar.
48
+ - **"Go back to Home."** The Get started page opens.
49
+
50
+ ### Teach the agent
51
+
52
+ - **"Remember that I prefer short answers."** The agent saves it to its
53
+ memory, and uses it in later chats.
54
+ - **"From now on, always explain your reasoning before answering."** The agent
55
+ can save this as a standing instruction.
56
+ - **"What do you remember about me?"** The agent reads its memory back to you.
57
+
58
+ ### Look at your data
59
+
60
+ - **"What tables are in this app's database?"** The agent reads the database
61
+ structure and lists the tables.
62
+ - **"How many chats do I have?"** The agent runs a read-only question against
63
+ the database and answers in the chat.
64
+
65
+ ### Learn the framework
66
+
67
+ - **"How do I add a new action to this app?"** The agent searches the Agent-Native
68
+ docs and explains the steps.
69
+ - **"What's the difference between an action and a skill?"** Same, answered
70
+ from the docs.
71
+
72
+ </Cards>
73
+
74
+ <Callout tone="info">
75
+
76
+ The agent reads the database but doesn't change it directly. To save new
77
+ information, it uses an action. That keeps every change on the same path the
78
+ app's own screens use. A developer can change this in the app's setup.
79
+
80
+ </Callout>
81
+
82
+ ## What's next
83
+
84
+ - [**Chat**](/docs/template-chat) — the overview
85
+ - [**Features**](/docs/template-chat-features) — conversations, the example action, teams, and admin pages
86
+ - [**Chat in a Multi-App Workspace**](/docs/template-chat-integrations) — connecting Chat to Dispatch and other apps
87
+ - [**Developer Guide**](/docs/template-chat-developers) — quick start, actions, the chat route, and adding your first feature
88
+ - [**Context Awareness**](/docs/context-awareness) — how the agent knows what's on your screen