@mindstudio-ai/remy 0.1.276 → 0.1.278

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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: Task Agents
3
- what: A full autonomous agent loop callable from any method. Give it a prompt, a set of tools, and an example of the output shape; the platform runs the model until it produces that shape — searching, scraping, generating images, retrying approaches that failed, and calling your app's own methods to read and write data as it goes. Tools can be any of the 1000+ SDK actions and your own methods in any combination, which is what makes it part of the app rather than a detached research bot. This is the difference between a feature that saves what the user typed and one that researches, enriches, and creates on their behalf, and it is one of the most powerful things the platform can do. Consider it whenever a feature would be dramatically more compelling if the app could do real work autonomously.
3
+ what: A full autonomous agent loop callable from any method. Give it a prompt, a set of tools, and a JSON Schema for the output shape; the platform runs the model until it produces validated output matching that schema — searching, scraping, generating images, retrying approaches that failed, and calling your app's own methods to read and write data as it goes. Tools can be any of the 1000+ SDK actions and your own methods in any combination, which is what makes it part of the app rather than a detached research bot. This is the difference between a feature that saves what the user typed and one that researches, enriches, and creates on their behalf, and it is one of the most powerful things the platform can do. Consider it whenever a feature would be dramatically more compelling if the app could do real work autonomously.
4
4
  when: Before writing any `mindstudio.runTask()` call — background enrichment, research-and-generate, anything where the model decides its own next step.
5
5
  ---
6
6
 
@@ -8,7 +8,7 @@ when: Before writing any `mindstudio.runTask()` call — background enrichment,
8
8
 
9
9
  A user types the name of a restaurant into your app, or uploads a photo of a storefront. The API call returns early, and in the background, a task agent searches Google, finds the official website, scrapes the address, gets the official social media accounts, and generates a stylized watercolor postcard of the exterior from images it found online. The user gets back a rich, illustrated card with the canonical name, website, address, and a custom image. A few tool calls (some in parallel), fully autonomous.
10
10
 
11
- `runTask()` makes this possible. It runs a multi-step, tool-use agent loop: give it a prompt, a set of tools, and an example of the structured output you want. The platform runs the loop (calling the model, executing tool calls, feeding results back) until the model produces JSON matching your output example. The model decides what to do next based on intermediate results — retrying searches with different terms, working around failed tools, batching independent calls in parallel.
11
+ `runTask()` makes this possible. It runs a multi-step, tool-use agent loop: give it a prompt, a set of tools, and a JSON Schema for the structured output you want (`outputSchema`). The platform runs the loop (calling the model, executing tool calls, feeding results back) until the model produces JSON conforming to your schema — validated every turn, with automatic repair when it doesn't. `result.output` is typed by inference from the schema: no generic argument, no manual validation. The model decides what to do next based on intermediate results — retrying searches with different terms, working around failed tools, batching independent calls in parallel.
12
12
 
13
13
  Tools are **SDK actions** (`searchGoogle`, `generateImage`, …) and **your own app's methods** (`{ appMethod: 'saveVendor' }`), in any combination. That second half is what makes a task agent part of your app rather than a detached research bot: it can read your tables to decide what to do next, and write results back itself instead of handing them to you to persist.
14
14
 
@@ -38,12 +38,7 @@ Run tasks in the background — depending on complexity they can take time to co
38
38
  ```typescript
39
39
  import { mindstudio } from '@mindstudio-ai/agent';
40
40
 
41
- const result = await mindstudio.runTask<{
42
- name: string;
43
- url: string;
44
- address: string;
45
- photoUrl: string;
46
- }>({
41
+ const result = await mindstudio.runTask({
47
42
  prompt: `You are a restaurant research assistant. Given a restaurant name,
48
43
  find its canonical name, website URL, full address, and create a stylized
49
44
  watercolor illustration of the restaurant exterior. Save the result before
@@ -61,30 +56,46 @@ const result = await mindstudio.runTask<{
61
56
  },
62
57
  ],
63
58
 
64
- structuredOutputExample: {
65
- name: 'Tartine Bakery',
66
- url: 'https://tartinebakery.com',
67
- address: '600 Guerrero St, San Francisco, CA 94110',
68
- photoUrl: 'https://cdn.mindstudio.ai/...',
59
+ outputSchema: {
60
+ type: 'object',
61
+ properties: {
62
+ name: { type: 'string' },
63
+ url: { type: ['string', 'null'] }, // nullable = a type array, never `nullable: true`
64
+ address: { type: 'string' },
65
+ photoUrl: { type: 'string' },
66
+ },
67
+ required: ['name', 'url', 'address', 'photoUrl'],
69
68
  },
70
69
 
71
70
  model: 'claude-5-sonnet', // ask askMindStudioSdk — don't copy this one blind
72
71
  maxTurns: 15,
73
72
  });
74
73
 
75
- // Always validate before using output
76
- if (!result.parsedSuccessfully) {
77
- console.error('Task failed to produce structured output:', result.outputRaw);
78
- throw new Error('Task agent failed');
79
- }
80
-
81
- console.log(result.output.name); // 'Tartine Bakery'
82
- console.log(result.output.photoUrl); // URL to the generated illustration
74
+ // result.output is typed from the schema — no generic argument, no validation.
75
+ console.log(result.output.name); // string
76
+ console.log(result.output.url); // string | null
83
77
  ```
84
78
 
85
- ## Always Validate Output
79
+ ## Output Contracts: `outputSchema` vs `structuredOutputExample`
86
80
 
87
- `runTask()` can return successfully with garbage output — fields null, data echoed back, or raw text instead of JSON. The result includes `parsedSuccessfully` to make this explicit. Always check it before using the output:
81
+ **With `outputSchema` (use this):** validation is built in. The schema is plain JSON Schema in the tool-definition dialect — `type`, `properties`, `required`, `enum`, `items`, nullability via type arrays like `['string', 'null']`. No `oneOf`/`anyOf`/`$ref`, no `nullable: true` — out-of-dialect schemas are rejected up front with `task_output_schema_unsupported`. Output is validated every turn and repaired automatically; `runTask()` either returns schema-conforming typed output or throws a `MindStudioError` with `code === 'task_output_schema_mismatch'` (raw text and validation errors in `err.details`). It never resolves with garbage, so use `result.output` directly and validate only domain invariants the schema can't express. For dynamic value sets, build the schema at runtime and put the set in an `enum` — the value is checked at runtime even though the type widens to `string`:
82
+
83
+ ```typescript
84
+ import type { JsonObjectSchema } from '@mindstudio-ai/agent';
85
+
86
+ const services = [...new Set(rows.map((r) => r.service))];
87
+ const result = await mindstudio.runTask({
88
+ // ...
89
+ outputSchema: {
90
+ type: 'object',
91
+ properties: { service: { enum: services } },
92
+ required: ['service'],
93
+ } as const satisfies JsonObjectSchema, // needed when the schema lives in a variable
94
+ // ...
95
+ });
96
+ ```
97
+
98
+ **With `structuredOutputExample` (legacy):** the output shape is suggested by example only, `output` is typed by your generic argument, and `runTask()` can return successfully with garbage — fields null, data echoed back, or raw text instead of JSON. Always check `parsedSuccessfully` before using the output:
88
99
 
89
100
  ```typescript
90
101
  const result = await mindstudio.runTask<MyType>({ ... });
@@ -151,7 +162,8 @@ When a task agent produces user-facing text, the prompt must state the voice and
151
162
  | `prompt` | Yes | — | System prompt defining the agent's behavior |
152
163
  | `input` | Yes | — | Structured input (passed as user message) |
153
164
  | `tools` | Yes | — | SDK action names and/or `{ appMethod, description }` entries, each with optional `defaults` |
154
- | `structuredOutputExample` | Yes | — | Object or JSON string showing expected output shape. Use realistic example values, not placeholders like `'string'` |
165
+ | `outputSchema` | One of these two | — | Plain JSON Schema for the output (`type`/`properties`/`required`/`enum`/`items`; nullable via type arrays, never `nullable: true`; no `oneOf`/`$ref`). Validated every turn with automatic repair; `result.output` typed from the schema. Use this |
166
+ | `structuredOutputExample` | One of these two | — | Legacy: object or JSON string showing expected output shape, unvalidated. Use realistic example values, not placeholders like `'string'`, and always check `parsedSuccessfully` |
155
167
  | `model` | Yes | — | Model ID (must support tool use). Ask `askMindStudioSdk` for the right one — MindStudio's ids don't match vendor ids, so a plausible-looking guess is usually wrong |
156
168
  | `maxTurns` | No | 20 | Max loop iterations (capped at 100) |
157
169
  | `onEvent` | No | — | SSE event callback for real-time streaming |
@@ -160,9 +172,9 @@ When a task agent produces user-facing text, the prompt must state the voice and
160
172
 
161
173
  ```typescript
162
174
  interface RunTaskResult<T> {
163
- output: T; // Parsed structured output matching your example
175
+ output: T; // With outputSchema: validated, typed from the schema. With an example: whatever parsed
164
176
  outputRaw: string; // Raw model text before JSON parse
165
- parsedSuccessfully: boolean; // Whether output was valid JSON
177
+ parsedSuccessfully: boolean; // Example mode only — always true in schema mode (a failure throws instead)
166
178
  turns: number; // Number of loop iterations used
167
179
  usage: {
168
180
  inputTokens: number;
@@ -201,22 +213,23 @@ Without `onEvent`, the SDK uses async polling (returns silently when complete).
201
213
  ## Error Handling
202
214
 
203
215
  - Model produces non-JSON output: retried automatically if turns remain
216
+ - With `outputSchema`, JSON that doesn't conform: the validation errors go back to the model as a repair turn (up to 3), then the call throws
204
217
  - Tool execution fails: error fed back to model, it can retry or work around it
205
218
  - An app method that throws: its actual error message goes back to the model, so a `MindStudioError` you throw deliberately ("vendor not found", "missing required field") is usable guidance the agent can act on. Worth throwing informative errors in methods you expose as tools
206
219
  - Max turns exceeded: one final forced output attempt with tools disabled
207
- - If output still can't be parsed: `parsedSuccessfully` will be `false`, raw text available in `outputRaw`
220
+ - Exhausted with nonconforming output: schema mode **throws** `task_output_schema_mismatch` (raw text and errors in `err.details`); example mode resolves with `parsedSuccessfully: false` and raw text in `outputRaw`
208
221
 
209
222
  ```typescript
210
223
  try {
211
- const result = await mindstudio.runTask({ ... });
212
- if (!result.parsedSuccessfully) {
213
- // Task completed but output wasn't valid JSON
214
- console.error('Raw output:', result.outputRaw);
215
- console.error('Tool calls:', result.toolCalls);
216
- }
224
+ const result = await mindstudio.runTask({ ...with outputSchema... });
225
+ // Conforming, typed output — use it directly.
226
+ await Table.update(id, result.output);
217
227
  } catch (err) {
218
228
  if (err instanceof MindStudioError) {
219
- // err.code: 'task_execution_error' | 'poll_token_expired' | 'stream_error'
229
+ // err.code: 'task_output_schema_mismatch' (couldn't produce conforming output;
230
+ // err.details has outputRaw + validation errors + toolCalls)
231
+ // | 'task_output_schema_unsupported' (schema uses out-of-dialect keywords)
232
+ // | 'task_execution_error' | 'poll_token_expired' | 'stream_error'
220
233
  }
221
234
  }
222
235
  ```