You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -135,7 +142,8 @@ and leave the field unannotated.
135
142
sent with their normal request semantics. A URL, domain, resource ID, control field, or opaque
136
143
payload is not model-visible merely because the provider is AI-backed or may process the
137
144
referenced resource later.
138
-
-**Text or structured content consumed by an AI model:** declare `request.modelInput` with
145
+
-**Text or structured content consumed by an AI model:** declare `request.modelInput` for an
146
+
external provider request or `operation.modelInput` for an in-process operation, with
139
147
`mode: 'project'` and select only the exact model-visible fields. The shared executor replaces
140
148
activated Sim secrets with canonical `{{NAME}}` labels before request formatting. For nested or
141
149
JSON-string fields, use a small shared selector plus `applyProjected`; verify that selecting the
@@ -144,20 +152,19 @@ and leave the field unannotated.
144
152
top-level param in `request.modelInput`. Project the private copy before the existing request
145
153
formatter parses it; keep formatter behavior deterministic when a whole-value placeholder is not
146
154
valid in the serialized grammar. Do not introduce a second hard-rejection path.
147
-
-**Opaque model input owned by an authenticated internal route** such as inline audio, image,
148
-
video, or document bytes: add `privateProvenance` to a projected request, or use
155
+
-**Opaque model input owned by an in-process operation** such as inline audio, image, video, or
156
+
document bytes: add `privateProvenance` to the operation model-input declaration, or use
149
157
`mode: 'private-provenance'` when there is no textual projection. Do not select storage keys,
150
-
paths, signed URLs, or ordinary remote URLs as byte provenance; the owning route must authorize
151
-
stored bytes independently at model egress. The route must call
158
+
paths, signed URLs, or ordinary remote URLs as byte provenance; the owning operation must
159
+
authorize stored bytes independently at model egress. The operation must call
152
160
`validateOpaqueModelInputProvenance` before downloading or sending content to the model and must
153
161
apply the workspace-file provenance guard before reading a persisted workspace file.
154
162
-**Sim-owned durable storage or internal execution handoff** that can later enter a workflow/model
155
163
(table cells, Agent memory, knowledge documents/chunks, workspace-file contents, or child-workflow
156
-
input): transport encrypted field-scoped provenance with `request.secretProvenance`. The
157
-
authenticated receiver validates the exact selection and scope, strips the private envelope, and
158
-
persists, imports, or propagates it at the owning boundary. Preserve shared legacy behavior for
159
-
headerless internal calls and rows/files whose provenance marker is `NULL`; never invent a
160
-
tool-local migration rule.
164
+
input): transport encrypted field-scoped provenance with `operation.secretProvenance`. The
165
+
operation validates the exact selection and trusted scope, then persists, imports, or propagates
166
+
it at the owning boundary. Preserve shared legacy behavior for rows/files whose provenance marker
167
+
is `NULL`; never invent a tool-local migration rule.
161
168
162
169
Hard rules:
163
170
@@ -166,7 +173,8 @@ Hard rules:
166
173
transport and strips private metadata from functional results.
167
174
- Never attach private provenance to an external URL or to `directExecution`. Project proven
168
175
model-visible external fields with `request.modelInput`; otherwise preserve ordinary request
169
-
semantics. Use an authenticated internal route when encrypted provenance must cross the boundary.
176
+
semantics. Use a registered in-process operation when encrypted provenance must cross the
177
+
boundary.
170
178
- Never sanitize arbitrary third-party tool results. Projection applies only to secrets activated
171
179
by Sim's resolved-secret provenance for that execution/tool call.
172
180
- Do not add provenance merely because a value is persisted, returned by a tool, or appears in a
@@ -596,6 +604,10 @@ If creating V2 versions (API-aligned outputs):
596
604
-[ ] Created `tools/{service}/` directory
597
605
-[ ] Created `types.ts` with all interfaces
598
606
-[ ] Created tool file for each operation
607
+
-[ ] Chose exactly one boundary per tool: registered `InternalToolConfig.operation` or absolute
608
+
external HTTP(S) `ToolConfig.request`
609
+
-[ ] No tool points to `/api/...`, constructs a URL back to Sim, declares `request.internal`, or
610
+
has an HTTP fallback for an in-process operation
599
611
-[ ] All params have correct visibility
600
612
-[ ] All nullable fields use `?? null`
601
613
-[ ] All optional outputs have `optional: true`
@@ -607,6 +619,8 @@ If creating V2 versions (API-aligned outputs):
607
619
external resource locators and control inputs retain their request semantics
608
620
-[ ] Confirmed ordinary third-party tool results are not generically sanitized
609
621
-[ ] Added provenance compatibility and fail-closed boundary tests where applicable
622
+
-[ ]`bun run check:tool-request-boundary` passes
623
+
-[ ] Internal-operation registry completeness test passes for every operation-backed tool
610
624
611
625
### Block
612
626
-[ ] Created `blocks/blocks/{service}.ts`
@@ -721,7 +735,8 @@ interface UserFile {
721
735
722
736
### File Input Pattern (Uploads)
723
737
724
-
For tools that accept file uploads, **always route through an internal API endpoint** rather than calling external APIs directly. This ensures proper file content retrieval.
738
+
File authorization, normalization, storage reads, provider upload, and response mapping belong in a
739
+
registered in-process operation. Do not create an internal API route for file tools.
725
740
726
741
#### 1. Block SubBlocks for File Input
727
742
@@ -757,137 +772,36 @@ Use the basic/advanced mode pattern:
757
772
758
773
#### 2. Normalize File Input in Block Config
759
774
760
-
In `tools.config.tool`, use `normalizeFileInput` to handle all input variants:
775
+
`tools.config.tool` selects the tool before variable resolution and must not mutate or coerce input.
776
+
Use `tools.config.params`, which runs after variable resolution, to normalize all file variants:
#### 3. Create Special Internal Tool Execution Route
783
-
784
-
Create `apps/sim/app/api/tools/{service}/{action}/route.ts`. This raw route pattern is only for an integration's provider-execution boundary when it needs special file normalization, large-body handling, or protocol behavior. It is not the pattern for CRUD or other operations on protected Sim resources. For those, use the `migrate-application-operation` skill and an authorized application use case with the ordinary internal/v2 route builders.
785
-
786
-
Internal tool routes are HTTP boundaries and follow the same contract policy as public routes — define the request/response shape in `apps/sim/lib/api/contracts/tools/{service}.ts` (or an existing aggregate) and validate with canonical helpers from `@/lib/api/server`. Never write a route-local Zod schema. Authenticate and perform cheap admission before parsing or downloading files.
793
+
#### 3. Define and register the in-process operation
0 commit comments