@mindstudio-ai/remy 0.1.261 → 0.1.263
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.
- package/dist/headless.js +7 -2
- package/dist/index.js +7 -2
- package/dist/prompt/compiled/auth.md +13 -1
- package/dist/prompt/compiled/interfaces.md +11 -2
- package/dist/prompt/compiled/manifest.md +1 -1
- package/dist/prompt/compiled/platform.md +6 -1
- package/dist/prompt/skills/agentInterfaces.md +27 -4
- package/dist/prompt/skills/mcpInterfaces.md +1 -1
- package/dist/prompt/skills/restApi.md +1 -1
- package/dist/prompt/skills/voiceInterfaces.md +359 -0
- package/dist/prompt/static/authoring.md +1 -1
- package/dist/prompt/static/intake.md +2 -2
- package/package.json +1 -1
package/dist/headless.js
CHANGED
|
@@ -483,13 +483,17 @@ var ALLOWED_MODELS_BY_TYPE = {
|
|
|
483
483
|
"gemini-3.1-pro",
|
|
484
484
|
"gemini-3-flash",
|
|
485
485
|
"gemini-3.5-flash",
|
|
486
|
+
"gemini-3.7-flash",
|
|
486
487
|
"grok-build-0.1",
|
|
487
488
|
"grok-4.5",
|
|
489
|
+
"grok-4.6",
|
|
488
490
|
"glm-5.2",
|
|
489
491
|
"muse-spark-1.1",
|
|
490
492
|
"kimi-k2-7-code",
|
|
491
493
|
"kimi-k3",
|
|
492
|
-
"deepseek-v4-flash-0731"
|
|
494
|
+
"deepseek-v4-flash-0731",
|
|
495
|
+
"qwen3.8-2.4t-a95b-deepinfra",
|
|
496
|
+
"minimax-m3"
|
|
493
497
|
]
|
|
494
498
|
// vision: undefined — unconstrained
|
|
495
499
|
// image_generation: undefined — unconstrained
|
|
@@ -2106,7 +2110,7 @@ var loadSkillTool = {
|
|
|
2106
2110
|
definition: {
|
|
2107
2111
|
clearable: true,
|
|
2108
2112
|
name: "loadSkill",
|
|
2109
|
-
description: "Load the full reference for a platform capability that isn't in your system prompt \u2014 task agents, agent interfaces, MCP interfaces, data sources. The available skills and the trigger for each are listed in <available_skills>. Load one before writing code in its area, not after: these are APIs where a plausible-looking guess is usually wrong. Calling this is cheap and expected \u2014 if you're unsure whether you need it, load it. Only covers the capabilities listed in the catalog; for backend SDK actions and model IDs use askMindStudioSdk.",
|
|
2113
|
+
description: "Load the full reference for a platform capability that isn't in your system prompt \u2014 task agents, agent interfaces, voice interfaces, MCP interfaces, data sources. The available skills and the trigger for each are listed in <available_skills>. Load one before writing code in its area, not after: these are APIs where a plausible-looking guess is usually wrong. Calling this is cheap and expected \u2014 if you're unsure whether you need it, load it. Only covers the capabilities listed in the catalog; for backend SDK actions and model IDs use askMindStudioSdk.",
|
|
2110
2114
|
inputSchema: {
|
|
2111
2115
|
type: "object",
|
|
2112
2116
|
properties: {
|
|
@@ -4323,6 +4327,7 @@ Each interface type invokes the same backend methods. Methods don't know which i
|
|
|
4323
4327
|
- Email \u2014 inbound email processing
|
|
4324
4328
|
- MCP \u2014 tool servers for AI assistants
|
|
4325
4329
|
- Agent \u2014 conversational LLM interface with tool access to backend methods
|
|
4330
|
+
- Voice \u2014 the app's agent as a realtime voice conversation, with the same tool access
|
|
4326
4331
|
|
|
4327
4332
|
## Backend
|
|
4328
4333
|
|
package/dist/index.js
CHANGED
|
@@ -2195,13 +2195,17 @@ var init_surfaces = __esm({
|
|
|
2195
2195
|
"gemini-3.1-pro",
|
|
2196
2196
|
"gemini-3-flash",
|
|
2197
2197
|
"gemini-3.5-flash",
|
|
2198
|
+
"gemini-3.7-flash",
|
|
2198
2199
|
"grok-build-0.1",
|
|
2199
2200
|
"grok-4.5",
|
|
2201
|
+
"grok-4.6",
|
|
2200
2202
|
"glm-5.2",
|
|
2201
2203
|
"muse-spark-1.1",
|
|
2202
2204
|
"kimi-k2-7-code",
|
|
2203
2205
|
"kimi-k3",
|
|
2204
|
-
"deepseek-v4-flash-0731"
|
|
2206
|
+
"deepseek-v4-flash-0731",
|
|
2207
|
+
"qwen3.8-2.4t-a95b-deepinfra",
|
|
2208
|
+
"minimax-m3"
|
|
2205
2209
|
]
|
|
2206
2210
|
// vision: undefined — unconstrained
|
|
2207
2211
|
// image_generation: undefined — unconstrained
|
|
@@ -2923,7 +2927,7 @@ var init_loadSkill = __esm({
|
|
|
2923
2927
|
definition: {
|
|
2924
2928
|
clearable: true,
|
|
2925
2929
|
name: "loadSkill",
|
|
2926
|
-
description: "Load the full reference for a platform capability that isn't in your system prompt \u2014 task agents, agent interfaces, MCP interfaces, data sources. The available skills and the trigger for each are listed in <available_skills>. Load one before writing code in its area, not after: these are APIs where a plausible-looking guess is usually wrong. Calling this is cheap and expected \u2014 if you're unsure whether you need it, load it. Only covers the capabilities listed in the catalog; for backend SDK actions and model IDs use askMindStudioSdk.",
|
|
2930
|
+
description: "Load the full reference for a platform capability that isn't in your system prompt \u2014 task agents, agent interfaces, voice interfaces, MCP interfaces, data sources. The available skills and the trigger for each are listed in <available_skills>. Load one before writing code in its area, not after: these are APIs where a plausible-looking guess is usually wrong. Calling this is cheap and expected \u2014 if you're unsure whether you need it, load it. Only covers the capabilities listed in the catalog; for backend SDK actions and model IDs use askMindStudioSdk.",
|
|
2927
2931
|
inputSchema: {
|
|
2928
2932
|
type: "object",
|
|
2929
2933
|
properties: {
|
|
@@ -5160,6 +5164,7 @@ Each interface type invokes the same backend methods. Methods don't know which i
|
|
|
5160
5164
|
- Email \u2014 inbound email processing
|
|
5161
5165
|
- MCP \u2014 tool servers for AI assistants
|
|
5162
5166
|
- Agent \u2014 conversational LLM interface with tool access to backend methods
|
|
5167
|
+
- Voice \u2014 the app's agent as a realtime voice conversation, with the same tool access
|
|
5163
5168
|
|
|
5164
5169
|
## Backend
|
|
5165
5170
|
|
|
@@ -214,6 +214,8 @@ All auth methods throw on failure with a `code` property:
|
|
|
214
214
|
| `invalid_state` | 400 | Sign in with Remy: returned CSRF state didn't match (stale/replayed redirect) |
|
|
215
215
|
| `popup_blocked` | — | Sign in with Remy (embedded): popup was blocked — prompt to allow popups and retry |
|
|
216
216
|
| `signin_timeout` | — | Sign in with Remy (embedded): popup didn't complete in time |
|
|
217
|
+
| `auth_required` | 401 | Agent/voice interface requires an authenticated user (interface `auth` block) |
|
|
218
|
+
| `role_required` | 403 | Agent/voice interface requires a role the user doesn't hold |
|
|
217
219
|
|
|
218
220
|
### Phone Helpers
|
|
219
221
|
|
|
@@ -380,9 +382,19 @@ Roles are declared in the manifest, stored as an array column on the user table,
|
|
|
380
382
|
- Writable from dashboard: Remy dashboard shows app users and their roles
|
|
381
383
|
- Backend enforcement: `auth.requireRole('admin')` works as before
|
|
382
384
|
|
|
385
|
+
## Interface-Level Auth (Agent + Voice)
|
|
386
|
+
|
|
387
|
+
Agent and voice interfaces additionally declare auth **in their config** (a required `auth` key:
|
|
388
|
+
`{ "requireUser": boolean, "requireRole"?: string[] }`) because those sessions spend money without
|
|
389
|
+
necessarily calling a backend method — the platform gates the lobby itself, before any model or
|
|
390
|
+
media spend. `requireRole` uses the same manifest role ids with OR semantics. Denials reach the
|
|
391
|
+
frontend SDK as `MindStudioInterfaceError` codes `auth_required` (401) and `role_required` (403) —
|
|
392
|
+
route them to the app's login flow. See the `agentInterfaces` / `voiceInterfaces` skills for the
|
|
393
|
+
full contract. Method-level `auth.requireRole(...)` checks still apply to every tool call inside.
|
|
394
|
+
|
|
383
395
|
## Apps Without Auth
|
|
384
396
|
|
|
385
|
-
Apps without `auth` in the manifest use anonymous guest sessions. No login, no user identity, no roles. This is the default and works fine for single-user apps, internal tools, and simple utilities.
|
|
397
|
+
Apps without `auth` in the manifest use anonymous guest sessions. No login, no user identity, no roles. This is the default and works fine for single-user apps, internal tools, and simple utilities. (Agent/voice interfaces on such apps declare `"auth": { "requireUser": false }` explicitly — anonymous callers are scoped by a per-browser visitor identity.)
|
|
386
398
|
|
|
387
399
|
## Important: Designing Auth in Web Interfaces
|
|
388
400
|
|
|
@@ -88,6 +88,8 @@ auth.logout() // clears session
|
|
|
88
88
|
|
|
89
89
|
For apps with an agent interface, the SDK also provides `createAgentChatClient()` for thread management and streaming chat. Load the `agentInterfaces` skill for its usage — thread APIs, streaming callbacks, and attachments are all there.
|
|
90
90
|
|
|
91
|
+
For apps with a voice interface, `createVoiceClient()` lives on the `@mindstudio-ai/interface/voice` subpath (deliberately separate so non-voice apps ship none of it). Load the `voiceInterfaces` skill for its usage — session lifecycle, live-caption events, tool status, and the voice-UI patterns are all there.
|
|
92
|
+
|
|
91
93
|
The project uses `"jsx": "react-jsx"` (automatic JSX transform) — do not `import React from 'react'`. Only import the specific hooks and types you need (e.g., `import { useState, useEffect } from 'react'`).
|
|
92
94
|
|
|
93
95
|
On deploy, the platform runs `npm install && npm run build` in the web directory and hosts the output on CDN.
|
|
@@ -180,10 +182,16 @@ It supports the full MCP surface: tools (methods the agent can call), resources
|
|
|
180
182
|
|
|
181
183
|
## Agent (Conversational Interface)
|
|
182
184
|
|
|
183
|
-
A conversational interface where an LLM has access to the app's methods as tools. Unlike MCP (which exposes methods for external agents), the agent interface IS the agent — it has its own personality, system prompt, and model config, and orchestrates tool calls against the app's methods internally. Chat runs as the authenticated user, so every tool call carries that user's roles.
|
|
185
|
+
A conversational interface where an LLM has access to the app's methods as tools. Unlike MCP (which exposes methods for external agents), the agent interface IS the agent — it has its own personality, system prompt, and model config, and orchestrates tool calls against the app's methods internally. Chat runs as the authenticated user, so every tool call carries that user's roles. The config must declare an `auth` block (`{ "requireUser": boolean, "requireRole"?: string[] }`) gating who may chat at all.
|
|
184
186
|
|
|
185
187
|
**Load the `agentInterfaces` skill** before authoring `src/interfaces/agent.md` or building the chat UI — the spec frontmatter, compiled output, `agent.json`, and the entire frontend surface are all there.
|
|
186
188
|
|
|
189
|
+
## Voice (Realtime Conversation)
|
|
190
|
+
|
|
191
|
+
The app's agent as a live voice conversation — the user talks, and the agent answers in sub-second, interruptible speech, calling methods mid-conversation. A sibling of the agent interface, not a mode of it: its own spec, a persona written for the ear rather than the screen, and a smaller toolset where every tool carries a latency class governing how the agent handles the wait out loud. Sessions run as the authenticated user, so tool calls carry that user's roles; the platform handles the realtime media, turn-taking, barge-in, and transcripts. The config must declare an `auth` block (`{ "requireUser": boolean, "requireRole"?: string[] }`) gating who may start a session at all.
|
|
192
|
+
|
|
193
|
+
**Load the `voiceInterfaces` skill** before authoring `src/interfaces/voice.md` or building the voice UI — the spoken-register rules, latency classes, spec format, `interface.json`, and the `createVoiceClient()` frontend surface are all there.
|
|
194
|
+
|
|
187
195
|
## Manifest Declaration
|
|
188
196
|
|
|
189
197
|
Each interface is declared in `mindstudio.json`:
|
|
@@ -197,7 +205,8 @@ Each interface is declared in `mindstudio.json`:
|
|
|
197
205
|
{ "type": "webhook", "path": "dist/interfaces/webhook/interface.json" },
|
|
198
206
|
{ "type": "email", "path": "dist/interfaces/email/interface.json" },
|
|
199
207
|
{ "type": "mcp", "path": "dist/interfaces/mcp/interface.json" },
|
|
200
|
-
{ "type": "agent", "path": "dist/interfaces/agent/agent.json" }
|
|
208
|
+
{ "type": "agent", "path": "dist/interfaces/agent/agent.json" },
|
|
209
|
+
{ "type": "voice", "path": "dist/interfaces/voice/interface.json" }
|
|
201
210
|
]
|
|
202
211
|
}
|
|
203
212
|
```
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
|
|
112
112
|
| Field | Type | Required | Description |
|
|
113
113
|
|-------|------|----------|-------------|
|
|
114
|
-
| `type` | `string` | Yes | One of: `web`, `api`, `cron`, `webhook`, `email`, `mcp`, `agent` |
|
|
114
|
+
| `type` | `string` | Yes | One of: `web`, `api`, `cron`, `webhook`, `email`, `mcp`, `agent`, `voice` |
|
|
115
115
|
| `path` | `string` | No | Path to the interface config file |
|
|
116
116
|
| `config` | `object` | No | Inline config (alternative to a file) |
|
|
117
117
|
| `enabled` | `boolean` | No | Default `true`. Set `false` to skip during build. |
|
|
@@ -23,6 +23,7 @@ my-app/
|
|
|
23
23
|
web.md web UI spec
|
|
24
24
|
api.md API conventions
|
|
25
25
|
agent.md agent personality and behavior spec
|
|
26
|
+
voice.md voice agent persona and toolset spec
|
|
26
27
|
cron.md scheduled job descriptions
|
|
27
28
|
roadmap/ feature roadmap (one file per item, type: roadmap)
|
|
28
29
|
|
|
@@ -53,6 +54,10 @@ my-app/
|
|
|
53
54
|
agent.json agent config
|
|
54
55
|
system.md compiled system prompt
|
|
55
56
|
tools/ tool descriptions (one .md per method)
|
|
57
|
+
voice/ voice interface
|
|
58
|
+
interface.json voice config
|
|
59
|
+
system.md compiled voice-register system prompt
|
|
60
|
+
tools/ tool descriptions (one .md per method)
|
|
56
61
|
```
|
|
57
62
|
|
|
58
63
|
## What Goes Where
|
|
@@ -95,7 +100,7 @@ const { vendor } = await api.approveVendor({ vendorId: '...' });
|
|
|
95
100
|
|
|
96
101
|
- **Managed databases.** SQLite with typed schemas. Push a schema change and the platform diffs, migrates, and promotes atomically.
|
|
97
102
|
- **Built-in auth.** Opt-in via manifest. Developer builds login UI, platform handles verification codes (email/SMS), cookie sessions, and role enforcement. Backend methods use `auth.requireRole('admin')` for access control.
|
|
98
|
-
- **Multiple interfaces, one codebase.** Web, API, Cron, Webhook, Email, MCP — all invoke the same methods. Methods don't know which interface called them.
|
|
103
|
+
- **Multiple interfaces, one codebase.** Web, API, Cron, Webhook, Email, MCP, Agent, Voice — all invoke the same methods. Methods don't know which interface called them.
|
|
99
104
|
- **Sandboxed execution.** Each method invocation runs in its own isolated execution context with npm packages pre-installed.
|
|
100
105
|
- **Git-native deployment.** Push to default branch to deploy. Push to feature branch for preview. Rollback is a git revert.
|
|
101
106
|
- **Secrets.** Encrypted environment variables with separate dev/prod values. Injected as `process.env` in methods. For third-party service credentials not covered by the SDK.
|
|
@@ -257,6 +257,7 @@ dist/interfaces/agent/
|
|
|
257
257
|
"temperature": 0.5,
|
|
258
258
|
"maxTokens": 16000,
|
|
259
259
|
"systemPrompt": "system.md",
|
|
260
|
+
"auth": { "requireUser": true },
|
|
260
261
|
"tools": [
|
|
261
262
|
{ "method": "create-todo", "description": "tools/createTodo.md" },
|
|
262
263
|
{ "method": "list-todos", "description": "tools/listTodos.md" }
|
|
@@ -276,6 +277,7 @@ across rather than copying the key.
|
|
|
276
277
|
| `temperature` | Model temperature |
|
|
277
278
|
| `maxTokens` | Max response tokens (the spec's `maxResponseTokens`) |
|
|
278
279
|
| `systemPrompt` | Relative path to the compiled system prompt markdown file |
|
|
280
|
+
| `auth` | **Required.** Who may open the lobby: `{ "requireUser": boolean, "requireRole"?: string[] }`. See the Auth section below |
|
|
279
281
|
| `tools` | Array of tool entries — `method` references a method `id` from the manifest, `description` is a relative path to a markdown file with rich tool docs (when to use, examples, edge cases, parameter guidance) |
|
|
280
282
|
| `webInterfacePath` | Optional. If the app has a web interface with a chat page, this path tells the IDE where to show the preview. Otherwise the agent is accessed via API. |
|
|
281
283
|
|
|
@@ -287,8 +289,29 @@ Declare it in `mindstudio.json`:
|
|
|
287
289
|
|
|
288
290
|
## Auth
|
|
289
291
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
292
|
+
**Every agent config declares an `auth` block.** Agent chat spends the owner's money on every
|
|
293
|
+
message without necessarily touching a backend method, so the platform gates the lobby itself —
|
|
294
|
+
enforced at thread creation and message send:
|
|
295
|
+
|
|
296
|
+
```json
|
|
297
|
+
"auth": { "requireUser": true, "requireRole": ["support-agent", "admin"] }
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
- `requireUser: true` — only authenticated app users may chat; `false` — anyone, including
|
|
301
|
+
anonymous visitors. Most apps want `true`; choose `false` deliberately (a public concierge).
|
|
302
|
+
- `requireRole` (optional) — the user must hold **at least one** of the listed manifest role ids
|
|
303
|
+
(OR semantics, same as the backend `auth.requireRole(...)`). Omit or leave empty for no role
|
|
304
|
+
gate. Requires `requireUser: true`. Unknown role ids fail the build.
|
|
305
|
+
- Denials surface to the frontend SDK as `MindStudioInterfaceError` with code `auth_required`
|
|
306
|
+
(401) or `role_required` (403).
|
|
307
|
+
- Dev preview is exempt — the builder is never locked out while testing.
|
|
308
|
+
- Older compiled apps without the block fall back to the manifest's `auth.enabled` (auth-enabled →
|
|
309
|
+
users only; no auth → public). New configs always declare it explicitly.
|
|
310
|
+
|
|
311
|
+
Once inside, agent chat runs as the **authenticated user**, not as a system role — tool calls
|
|
312
|
+
carry that user's roles, so a method gated with `auth.requireRole` behaves exactly as it would if
|
|
313
|
+
the user had called it from the web frontend. That's what makes exposing real methods safe; it's
|
|
314
|
+
also why role restrictions belong in the tool descriptions, so the agent can decline gracefully
|
|
315
|
+
instead of surfacing a rejection. Anonymous visitors (when allowed) are scoped by a per-browser
|
|
316
|
+
visitor identity: their threads are private to their browser, and gated methods still reject.
|
|
294
317
|
|
|
@@ -268,7 +268,7 @@ Declare it in `mindstudio.json`:
|
|
|
268
268
|
`custom_subdomain` host (e.g. `myapp.madewithremy.com`), a custom domain if configured, or the UUID
|
|
269
269
|
host (`<appId>.madewithremy.com` / `.msagent.ai`).
|
|
270
270
|
- **Auth is optional.** A `Bearer` key resolves to a user with full RBAC, so the method's own
|
|
271
|
-
`auth.requireRole`/`
|
|
271
|
+
`auth.requireRole(...)`/`hasRole(...)` checks apply as they would for that user. With no key, calls run
|
|
272
272
|
anonymously — no user, no roles. The method is the boundary: gate sensitive tools, and understand that
|
|
273
273
|
a public (keyless) server effectively exposes only the un-gated ones.
|
|
274
274
|
- Input schemas are derived automatically from each method's input contract.
|
|
@@ -141,7 +141,7 @@ Routes are mounted at `/_/api{path}` (e.g. `DELETE /_/api/vendors/abc123`).
|
|
|
141
141
|
- **Request body** for POST/PUT/PATCH is the input directly (no `{ input: {...} }` wrapper)
|
|
142
142
|
- **Response** is the method output directly (no `{ output: {...} }` wrapper)
|
|
143
143
|
- **Auth** via `Authorization: Bearer sk_...` — an API key resolves to a user with full RBAC, so the
|
|
144
|
-
method's own `auth.requireRole`/`
|
|
144
|
+
method's own `auth.requireRole(...)`/`hasRole(...)` checks apply exactly as they would for that user
|
|
145
145
|
- **Streaming**: `Accept: text/event-stream` header returns SSE chunks
|
|
146
146
|
- **Raw request context**: Every API method receives `input._request` with `{ method, headers, rawBody }`.
|
|
147
147
|
`rawBody` is the original unparsed body as a UTF-8 string — needed for signature verification, since
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Voice Interfaces
|
|
3
|
+
what: Realtime voice conversation as a first-class interface — the user talks to the app and its voice agent talks back in sub-second, interruptible speech, calling the app's methods mid-conversation as the authenticated user. The platform handles the media transport, turn-taking, barge-in, and transcripts, so the work is authorship — a persona written for the ear, a small toolset where every tool carries a latency class, and descriptions that say results out loud. Any app whose methods do something interesting can pick up a voice, and it is often the most impressive surface it has.
|
|
4
|
+
when: Before authoring `src/interfaces/voice.md`, choosing a voice model or pipeline, deciding which methods a voice agent gets, or building the voice UI with `createVoiceClient()`.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Building Voice Interfaces
|
|
8
|
+
|
|
9
|
+
A voice interface is the app's agent as a live phone-call-quality conversation: the user speaks, the
|
|
10
|
+
agent answers in speech, and the app's methods are its tools. It is a **sibling of the agent
|
|
11
|
+
interface, not a mode of it** — the two share a philosophy (an LLM projecting the backend contract
|
|
12
|
+
into conversation; load the `agentInterfaces` skill for that shared ground), but everything you
|
|
13
|
+
author differs. The persona is written for the ear, not the screen. The toolset is smaller and
|
|
14
|
+
curated for conversational latency. And every tool declares how the agent should handle the wait,
|
|
15
|
+
because in a live call, silence reads as a dropped line.
|
|
16
|
+
|
|
17
|
+
The platform owns the hard parts — realtime audio transport, turn detection, interruption handling,
|
|
18
|
+
transcripts, session limits, per-user auth on every tool call. Your job is the spec
|
|
19
|
+
(`src/interfaces/voice.md`) and its compilation into `dist/interfaces/voice/`.
|
|
20
|
+
|
|
21
|
+
## Voice Agent Design
|
|
22
|
+
|
|
23
|
+
### Written for the ear
|
|
24
|
+
|
|
25
|
+
Everything the agent produces gets spoken aloud. That inverts several habits that are correct
|
|
26
|
+
everywhere else, and the compiled system prompt must carry them explicitly:
|
|
27
|
+
|
|
28
|
+
- **No visual formatting, ever.** No markdown, no lists, no tables, no emoji, no URLs read as
|
|
29
|
+
punctuation soup. If a tool returns a link, say what it is and where it will be, don't recite it.
|
|
30
|
+
- **Spoken-form values.** "Forty-two fifty," not "$42.50". "Two fifteen in the afternoon," not
|
|
31
|
+
"14:15". Read email addresses and confirmation codes character by character, and read them *back*
|
|
32
|
+
for confirmation before acting on them — mishearing one digit of a phone number is the classic
|
|
33
|
+
voice failure.
|
|
34
|
+
- **Brevity is a hard rule, not a style preference.** One to two sentences per turn, one question at
|
|
35
|
+
a time. A paragraph that reads fine in chat is a monologue on a call.
|
|
36
|
+
- **Handle unclear audio explicitly.** Give the prompt a rule for it: respond only to clear audio;
|
|
37
|
+
if it's noisy or ambiguous, ask the user to repeat — never guess, and never call a tool on input
|
|
38
|
+
the agent isn't sure it heard.
|
|
39
|
+
- **Pin the language.** State the response language in the prompt; don't let the model infer it from
|
|
40
|
+
an accent.
|
|
41
|
+
|
|
42
|
+
Beyond the mechanics, the persona itself should be *of the ear*: pacing, warmth, how it handles
|
|
43
|
+
being interrupted, what it says when it needs a second. This is the fun part, same as the agent
|
|
44
|
+
interface — a distinct character beats a generic assistant, and voice makes character land harder
|
|
45
|
+
than any other surface.
|
|
46
|
+
|
|
47
|
+
### The latency classes
|
|
48
|
+
|
|
49
|
+
Every tool in the spec declares one of three classes. This is the voice-specific discipline — get it
|
|
50
|
+
right and tool use feels like talking to a competent person; get it wrong and every action is an
|
|
51
|
+
awkward pause.
|
|
52
|
+
|
|
53
|
+
- **`fast`** — sub-second reads: lookups, availability checks, small queries. The agent calls
|
|
54
|
+
silently; announcing a sub-second call adds more delay than the call itself.
|
|
55
|
+
- **`slow`** — a noticeable wait, roughly one to three seconds: writes, searches, anything that does
|
|
56
|
+
real work. The agent speaks a one-line preamble ("Let me get that booked") generated in parallel
|
|
57
|
+
with the call, so the line never goes quiet.
|
|
58
|
+
- **`background`** — long-running work: reports, enrichment, bulk operations. The agent
|
|
59
|
+
acknowledges, keeps conversing, and reports the result when it lands. Background tools are
|
|
60
|
+
cancellable — if the user changes course mid-run, the work stops.
|
|
61
|
+
|
|
62
|
+
Classify by how the method actually behaves, not by what it is named. A "lookup" that fans out to an
|
|
63
|
+
external service is `slow`. When in doubt between `fast` and `slow`, pick `slow` — a needless
|
|
64
|
+
preamble is mildly chatty; an unexplained silence feels broken.
|
|
65
|
+
|
|
66
|
+
### Tool descriptions say results out loud
|
|
67
|
+
|
|
68
|
+
Follow the agent-interface principles for tool descriptions (when to use and when not, parameter
|
|
69
|
+
guidance, what comes back) — plus one voice-specific layer: **how to speak the result.** A tool that
|
|
70
|
+
returns a booking record needs its description to say what the confirmation sounds like ("You're all
|
|
71
|
+
set for Tuesday at two") and what never gets read aloud (internal ids, timestamps, enum values).
|
|
72
|
+
|
|
73
|
+
Curate harder than you would for chat. A voice agent with four excellent tools outperforms one with
|
|
74
|
+
twelve adequate ones — every tool the model considers is a beat of hesitation. Skip batch
|
|
75
|
+
operations, admin utilities, and anything whose output can't be said in a breath or two. Note role
|
|
76
|
+
restrictions in the description so the agent declines gracefully in character instead of surfacing a
|
|
77
|
+
rejection.
|
|
78
|
+
|
|
79
|
+
### Confirmation scales with risk
|
|
80
|
+
|
|
81
|
+
Bake the policy into the system prompt: read-only tools — just call them. Writes — summarize what's
|
|
82
|
+
about to happen and get a yes. Anything destructive or financial — read the details back first,
|
|
83
|
+
piece by piece. In voice there is no confirmation dialog to lean on; the conversation *is* the
|
|
84
|
+
confirmation UI.
|
|
85
|
+
|
|
86
|
+
### Choosing the model
|
|
87
|
+
|
|
88
|
+
Two shapes, one `model` field:
|
|
89
|
+
|
|
90
|
+
- **Native speech-to-speech** (`{"model": ..., "voice": ...}`) — one realtime model hears and
|
|
91
|
+
speaks. Lowest latency, most natural prosody, hears tone and hesitation. The default for
|
|
92
|
+
personality-forward, conversational apps.
|
|
93
|
+
- **Cascaded** (`{"llm": ..., "stt": ..., "tts": ..., "voice": ...}`) — streaming transcription
|
|
94
|
+
into any chat model in the catalog, streaming speech out. Slightly higher latency, but the brain
|
|
95
|
+
can be *any* chat model — the right choice when the app's reasoning demands a specific model, or
|
|
96
|
+
when the agent interface already uses one and the voice should think identically. The blessed
|
|
97
|
+
streaming pairing is `"stt": "deepgram-nova-3", "tts": "cartesia-sonic-3"` — the lowest-latency
|
|
98
|
+
combination the platform wires; prefer it unless there's a reason not to. One nuance: cascaded
|
|
99
|
+
engines speak the `greeting` verbatim (they have a real TTS); speech-to-speech engines have the
|
|
100
|
+
model say it, so it may paraphrase slightly.
|
|
101
|
+
|
|
102
|
+
Ask `askMindStudioSdk` for available ids — realtime, transcription, and speech models are separate
|
|
103
|
+
catalogs, and MindStudio ids don't match vendor ids, so treat ids in this document as illustrative.
|
|
104
|
+
Voice ids are model-specific; query for those too. The user's UI has a picker for changing the model
|
|
105
|
+
later, so validate only when you set it.
|
|
106
|
+
|
|
107
|
+
### Seeding from an existing agent
|
|
108
|
+
|
|
109
|
+
If the app already has an agent interface, start from it: same character, same values, same
|
|
110
|
+
terminology — then rewrite for the ear (shorter, spoken-form, no formatting) and re-curate the
|
|
111
|
+
toolset for latency. Don't copy `agent.md`'s prose wholesale; a chat persona read aloud sounds like
|
|
112
|
+
someone reading chat aloud.
|
|
113
|
+
|
|
114
|
+
### Anti-patterns
|
|
115
|
+
|
|
116
|
+
- Prose that would render fine in chat — bullet lists, headers, or markdown anywhere in `system.md`.
|
|
117
|
+
- A tool description that explains what to display instead of what to say.
|
|
118
|
+
- Exposing the whole method surface. Voice is the most curated interface the app has.
|
|
119
|
+
- A generic greeting ("Hello! How can I assist you today?"). The greeting is the first thing anyone
|
|
120
|
+
hears; make it the character's.
|
|
121
|
+
- Writing your own current-user placeholder — the platform appends a `## Current User` block (name,
|
|
122
|
+
roles) to every system prompt at runtime.
|
|
123
|
+
|
|
124
|
+
## Compiling the Voice Spec
|
|
125
|
+
|
|
126
|
+
When building `dist/interfaces/voice/`, consider the spec, the app, and the `@brand/` guidelines —
|
|
127
|
+
the voice agent should be unmistakably the same product as the web UI, projected into sound. Output:
|
|
128
|
+
|
|
129
|
+
**`system.md`** — the persona compiled for the ear. Character first, then the mandatory carries from
|
|
130
|
+
"Written for the ear" above (spoken-form rules, brevity, unclear-audio handling, language pinning,
|
|
131
|
+
confirmation-by-risk), then any preamble phrasing guidance for `slow` tools so the fillers sound like
|
|
132
|
+
the character too.
|
|
133
|
+
|
|
134
|
+
**`tools/*.md`** — one per tool: when to use, parameter guidance, how to say the result, role
|
|
135
|
+
restrictions.
|
|
136
|
+
|
|
137
|
+
**`interface.json`** — the config tying it together. Full shape in "The wiring" below.
|
|
138
|
+
|
|
139
|
+
## Voice UI
|
|
140
|
+
|
|
141
|
+
When the app has a web interface, voice arrives as a **layer over it**, not a separate page: a
|
|
142
|
+
persistent affordance (a button, an orb in a corner) that starts a session in place, with the app
|
|
143
|
+
still visible and usable. A dedicated full-screen voice mode is the immersive option for apps where
|
|
144
|
+
the conversation *is* the product — earn it, don't default to it.
|
|
145
|
+
|
|
146
|
+
### Frontend SDK: `createVoiceClient()`
|
|
147
|
+
|
|
148
|
+
Ships as a subpath of the interface SDK so apps that never use voice pay nothing for it. All voice
|
|
149
|
+
UIs go through it — never hand-roll audio capture or transport.
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { createVoiceClient } from '@mindstudio-ai/interface/voice';
|
|
153
|
+
|
|
154
|
+
const voice = createVoiceClient();
|
|
155
|
+
|
|
156
|
+
// Prompts for mic permission, mints a session, connects.
|
|
157
|
+
// Throws MindStudioInterfaceError('microphone_denied') on refusal.
|
|
158
|
+
const session = await voice.startSession();
|
|
159
|
+
|
|
160
|
+
session.state; // 'connecting' | 'listening' | 'thinking' | 'speaking' | 'ended'
|
|
161
|
+
session.on('stateChange', (state) => { }); // on() returns an unsubscribe fn
|
|
162
|
+
|
|
163
|
+
// Live captions, both sides. Each event carries the segment's FULL text so
|
|
164
|
+
// far (never a delta) — render by upserting on segmentId, not appending.
|
|
165
|
+
session.on('transcript', ({ role, segmentId, text, final }) => { });
|
|
166
|
+
|
|
167
|
+
session.on('toolCall', ({ method, status }) => { }); // 'running' | 'done' | 'failed'
|
|
168
|
+
session.on('error', (err) => { });
|
|
169
|
+
|
|
170
|
+
session.mute(); session.unmute(); session.isMuted;
|
|
171
|
+
session.sendText('123 Main Street'); // inject text into the live conversation
|
|
172
|
+
session.end();
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Agent audio playback is handled inside the SDK (a hidden autoplaying element) — never create audio
|
|
176
|
+
elements for the agent. `startSession()` throws `MindStudioInterfaceError` with code
|
|
177
|
+
`microphone_denied` when mic access is refused (surface that state gently in the UI),
|
|
178
|
+
`voice_concurrency_limit` / `voice_visitor_limit` when the app's session limits are hit, and
|
|
179
|
+
`auth_required` (401) / `role_required` (403) when the interface's `auth` block denies the caller
|
|
180
|
+
(route those to the app's login flow).
|
|
181
|
+
|
|
182
|
+
Past sessions are call records with transcripts: `voice.listSessions()` /
|
|
183
|
+
`voice.getSession(id)` — the material for a history view if the app wants one.
|
|
184
|
+
|
|
185
|
+
### The state machine, made visible
|
|
186
|
+
|
|
187
|
+
One audio-reactive element carries the session: idle → connecting → listening → thinking → speaking.
|
|
188
|
+
Always pair it with a **text state label** — never signal state by color or motion alone. Calm at
|
|
189
|
+
idle, responsive to actual audio levels while listening and speaking. Respect
|
|
190
|
+
`prefers-reduced-motion` with a static-but-labeled variant.
|
|
191
|
+
|
|
192
|
+
### Live captions
|
|
193
|
+
|
|
194
|
+
Stream `transcript` events as captions — both sides of the conversation. Captions make the agent
|
|
195
|
+
feel accurate, catch mishearings early, and are the accessibility story. User-side transcripts
|
|
196
|
+
arrive as recognition output and can lag or differ slightly from what the model heard; render them
|
|
197
|
+
as captions, never treat them as input to app logic.
|
|
198
|
+
|
|
199
|
+
### Controls that must exist
|
|
200
|
+
|
|
201
|
+
**Mute** and **end call**, always visible, always working. `sendText` earns its place the moment the
|
|
202
|
+
conversation needs an exact string — an address, a code, an email — typing it beats spelling it
|
|
203
|
+
aloud three times. Show tool activity as a compact inline status from `toolCall` events, in the
|
|
204
|
+
app's voice ("Booking your appointment…"), never raw names or JSON.
|
|
205
|
+
|
|
206
|
+
### Anti-patterns
|
|
207
|
+
|
|
208
|
+
- Blocking the whole UI behind the session — voice is a layer, the app stays usable.
|
|
209
|
+
- An orb with no label, or state changes conveyed only by color.
|
|
210
|
+
- Rendering user-side captions as authoritative ("you said X") — they're recognition output.
|
|
211
|
+
- Auto-starting a session on page load. Microphone access is always a deliberate user action.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
# The wiring
|
|
216
|
+
|
|
217
|
+
## Spec: `src/interfaces/voice.md`
|
|
218
|
+
|
|
219
|
+
Frontmatter holds the structured fields; the body is the persona plus an explicit `## Tools`
|
|
220
|
+
section.
|
|
221
|
+
|
|
222
|
+
```yaml
|
|
223
|
+
---
|
|
224
|
+
name: Front Desk
|
|
225
|
+
description: Books appointments and answers questions by voice.
|
|
226
|
+
type: interface/voice
|
|
227
|
+
model: {"model": "gpt-realtime-mini", "voice": "marin"}
|
|
228
|
+
turnDetection: {"eagerness": "medium"}
|
|
229
|
+
greeting: Hey! I can help you book, reschedule, or answer questions — what do you need?
|
|
230
|
+
---
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Frontmatter fields:
|
|
234
|
+
|
|
235
|
+
- `name` — display name
|
|
236
|
+
- `description` — one-liner for listings
|
|
237
|
+
- `model` — JSON string, two shapes: native speech-to-speech `{"model": <realtime model id>,
|
|
238
|
+
"voice": <voice id>}`, or cascaded `{"llm": <chat model id>, "stt": <transcription model id>,
|
|
239
|
+
"tts": <speech model id>, "voice": <voice id>}`. Optional `config` for model-specific settings.
|
|
240
|
+
Ids via `askMindStudioSdk`.
|
|
241
|
+
- `turnDetection` — optional; `{"eagerness": "low" | "medium" | "high"}` — how quickly the platform
|
|
242
|
+
decides the user finished speaking. High is snappier; low is more patient (users dictating
|
|
243
|
+
numbers or addresses). Default `medium`.
|
|
244
|
+
- `greeting` — optional spoken opener, delivered on session start. Omit and the agent waits for the
|
|
245
|
+
user to speak first. Verbatim on cascaded engines; model-spoken (may paraphrase) on
|
|
246
|
+
speech-to-speech.
|
|
247
|
+
|
|
248
|
+
Body: persona prose (voice register), then the toolset:
|
|
249
|
+
|
|
250
|
+
```markdown
|
|
251
|
+
## Tools
|
|
252
|
+
|
|
253
|
+
### Book appointment
|
|
254
|
+
method: book-appointment
|
|
255
|
+
latency: slow
|
|
256
|
+
~~~
|
|
257
|
+
Book an appointment once the caller has confirmed a date, time, and service.
|
|
258
|
+
Read the details back and get a yes before calling. Say the confirmation
|
|
259
|
+
naturally ("You're all set for Tuesday the 4th at 2pm") — never read the
|
|
260
|
+
booking id aloud unless asked.
|
|
261
|
+
~~~
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
`latency` is one of `fast` / `slow` / `background` (semantics in "The latency classes" above).
|
|
265
|
+
Don't hand-author input schemas — the platform derives them from the method contract.
|
|
266
|
+
|
|
267
|
+
## Compiled Output: `dist/interfaces/voice/`
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
dist/interfaces/voice/
|
|
271
|
+
├── interface.json ← config the platform reads
|
|
272
|
+
├── system.md ← compiled voice-register system prompt
|
|
273
|
+
└── tools/
|
|
274
|
+
└── bookAppointment.md ← rich tool description, one per tool
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Config (`interface.json`)
|
|
278
|
+
|
|
279
|
+
The top-level key must match the interface type (`voice`):
|
|
280
|
+
|
|
281
|
+
```json
|
|
282
|
+
{
|
|
283
|
+
"voice": {
|
|
284
|
+
"name": "Front Desk",
|
|
285
|
+
"description": "Books appointments and answers questions by voice.",
|
|
286
|
+
"model": "gpt-realtime-mini",
|
|
287
|
+
"voice": "marin",
|
|
288
|
+
"turnDetection": { "eagerness": "medium" },
|
|
289
|
+
"greeting": "Hey! I can help you book, reschedule, or answer questions — what do you need?",
|
|
290
|
+
"systemPrompt": "system.md",
|
|
291
|
+
"auth": { "requireUser": true },
|
|
292
|
+
"tools": [
|
|
293
|
+
{ "method": "book-appointment", "latency": "slow", "description": "tools/bookAppointment.md" }
|
|
294
|
+
],
|
|
295
|
+
"webInterfacePath": "/"
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
| Field | Description |
|
|
301
|
+
|-------|-------------|
|
|
302
|
+
| `name`, `description` | Display name + listing metadata |
|
|
303
|
+
| `model` | Realtime model id (native speech-to-speech). Mutually exclusive with `llm`/`stt`/`tts` |
|
|
304
|
+
| `llm`, `stt`, `tts` | The cascaded alternative: chat model id + streaming transcription id + streaming speech id |
|
|
305
|
+
| `voice` | Provider voice id (model-specific; query `askMindStudioSdk`) |
|
|
306
|
+
| `turnDetection` | `{ "eagerness": "low" \| "medium" \| "high" }`, optional |
|
|
307
|
+
| `greeting` | Optional spoken opener |
|
|
308
|
+
| `systemPrompt` | Relative path to the compiled system prompt |
|
|
309
|
+
| `auth` | **Required.** Who may start a session: `{ "requireUser": boolean, "requireRole"?: string[] }`. See the Auth section below |
|
|
310
|
+
| `tools` | `{ method, latency, description }` — method `id` from the manifest, a latency class, and a relative path to the tool's markdown |
|
|
311
|
+
| `webInterfacePath` | Optional. Where the voice layer lives in the web interface, for the editor preview |
|
|
312
|
+
|
|
313
|
+
Declare it in `mindstudio.json`:
|
|
314
|
+
|
|
315
|
+
```json
|
|
316
|
+
{ "type": "voice", "path": "dist/interfaces/voice/interface.json" }
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Platform Behavior
|
|
320
|
+
|
|
321
|
+
- Input schemas are derived from each method's contract — never hand-written.
|
|
322
|
+
- The platform appends a `## Current User` block (name, roles) to the system prompt at runtime;
|
|
323
|
+
never author a placeholder for it.
|
|
324
|
+
- Turn detection, barge-in (interruption truncates the agent's context to the audio the user
|
|
325
|
+
actually heard), and background-noise handling are platform-managed; `turnDetection.eagerness` is
|
|
326
|
+
the only knob.
|
|
327
|
+
- Sessions have a per-app concurrency limit and a maximum duration, both configurable in the app's
|
|
328
|
+
settings; an idle session is ended gracefully after a prompt. Voice minutes and model usage are
|
|
329
|
+
metered.
|
|
330
|
+
- Every session persists as a call record with a transcript, visible in the dashboard and readable
|
|
331
|
+
from the frontend via `voice.listSessions()` / `voice.getSession(id)`.
|
|
332
|
+
|
|
333
|
+
## Auth
|
|
334
|
+
|
|
335
|
+
**Every voice config declares an `auth` block.** A voice session spends the owner's money for its
|
|
336
|
+
entire duration without necessarily touching a backend method, so the platform gates session
|
|
337
|
+
creation itself:
|
|
338
|
+
|
|
339
|
+
```json
|
|
340
|
+
"auth": { "requireUser": true, "requireRole": ["member"] }
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
- `requireUser: true` — only authenticated app users may start a session; `false` — anyone,
|
|
344
|
+
including anonymous visitors. Most apps want `true`; choose `false` deliberately (a public
|
|
345
|
+
front-desk line).
|
|
346
|
+
- `requireRole` (optional) — the user must hold **at least one** of the listed manifest role ids
|
|
347
|
+
(OR semantics, same as the backend `auth.requireRole(...)`). Omit or leave empty for no role
|
|
348
|
+
gate. Requires `requireUser: true`. Unknown role ids fail the build.
|
|
349
|
+
- Denials reject `startSession()` with code `auth_required` (401) or `role_required` (403).
|
|
350
|
+
- Dev preview is exempt — the builder is never locked out while testing.
|
|
351
|
+
- Older compiled apps without the block fall back to the manifest's `auth.enabled` (auth-enabled →
|
|
352
|
+
users only; no auth → public). New configs always declare it explicitly.
|
|
353
|
+
|
|
354
|
+
Once inside, voice sessions run as the **authenticated user** — every tool call carries that
|
|
355
|
+
user's roles, so a method gated with `auth.requireRole` behaves exactly as it would from the web
|
|
356
|
+
frontend or the agent interface. Anonymous sessions (when allowed) have no user and no roles:
|
|
357
|
+
gated methods reject, and the caller's history is scoped to their browser's visitor identity.
|
|
358
|
+
That's why role restrictions belong in the tool descriptions — the agent should decline in
|
|
359
|
+
character, not relay a rejection.
|
|
@@ -19,7 +19,7 @@ The scaffold starts with these spec files that cover the full picture of the app
|
|
|
19
19
|
- **`src/interfaces/@brand/voice.md`** — voice and terminology: tone, error messages, word choices
|
|
20
20
|
- **`src/roadmap/`** — feature roadmap. One file per feature (`type: roadmap`). See "Roadmap" below.
|
|
21
21
|
|
|
22
|
-
These are starting points, not constraints. Create as many spec files as the project needs — the `src/` folder is your workspace and every `.md` file in it becomes compilation context. If the app has substantial content (presentation slides, copy, lesson plans, menu items, quiz questions), put it in its own file (`src/content.md`, `src/slides.md`, `src/menu.md`, etc.) rather than cramming it into `app.md` or `web.md`. If the domain is complex, split `app.md` into multiple files by area (`src/billing.md`, `src/approvals.md`). Add interface specs for other interface types (`api.md`, `webhook.md`, `cron.md`, `email.md`, `mcp.md`, `agent.md`) if the app uses them. Each of those has a skill carrying its spec format and config — `restApi`, `webhooks`, `scheduledJobs`, `inboundEmail`, `mcpInterfaces`, `agentInterfaces` — and you should load the relevant one before writing the spec rather than after, since the spec is what the config is compiled from. For external HTTP the choice is between two of them: the Webhook interface handles inbound provider webhooks (Stripe, GitHub) via secret-in-URL routing, while the API interface covers bearer-auth sync endpoints, public REST APIs, and batch tools. Organize however serves clarity — the platform reads the entire `src/` folder.
|
|
22
|
+
These are starting points, not constraints. Create as many spec files as the project needs — the `src/` folder is your workspace and every `.md` file in it becomes compilation context. If the app has substantial content (presentation slides, copy, lesson plans, menu items, quiz questions), put it in its own file (`src/content.md`, `src/slides.md`, `src/menu.md`, etc.) rather than cramming it into `app.md` or `web.md`. If the domain is complex, split `app.md` into multiple files by area (`src/billing.md`, `src/approvals.md`). Add interface specs for other interface types (`api.md`, `webhook.md`, `cron.md`, `email.md`, `mcp.md`, `agent.md`, `voice.md`) if the app uses them. Each of those has a skill carrying its spec format and config — `restApi`, `webhooks`, `scheduledJobs`, `inboundEmail`, `mcpInterfaces`, `agentInterfaces`, `voiceInterfaces` — and you should load the relevant one before writing the spec rather than after, since the spec is what the config is compiled from. For external HTTP the choice is between two of them: the Webhook interface handles inbound provider webhooks (Stripe, GitHub) via secret-in-URL routing, while the API interface covers bearer-auth sync endpoints, public REST APIs, and batch tools. Organize however serves clarity — the platform reads the entire `src/` folder.
|
|
23
23
|
|
|
24
24
|
Remember: users care about look and feel as much as (and often more than) underlying data structures. Don't treat the brand and interface specs as an afterthought — for many users, the visual identity and voice are the first things they want to get right.
|
|
25
25
|
|
|
@@ -11,7 +11,7 @@ Remy apps are full-stack TypeScript projects. You have a lot to work with:
|
|
|
11
11
|
- **Backend (Methods):** TypeScript in a sandboxed runtime. Any npm package. Managed SQLite database with typed schemas and automatic migrations. Built-in app-managed auth with email/SMS verification, cookie sessions, and role enforcement. None of these are required — use what the app needs.
|
|
12
12
|
- **Frontend (Web Interface):** Starts as Vite + React, but any TypeScript project with a build command works. Any framework, any library, or no framework at all.
|
|
13
13
|
- **AI & integrations:** The `@mindstudio-ai/agent` SDK gives access to 200+ AI models (OpenAI, Anthropic, Google, Meta, Mistral, and more) and 1000+ integrations (email, SMS, Slack, HubSpot, Google Workspace, web scraping, image/video generation, media processing) with zero configuration — credentials are handled automatically. No API keys needed. Beyond individual actions, `runTask()` lets you spin up lightweight autonomous task agents that chain these actions together with judgment — e.g., a user types a restaurant name and the backend autonomously researches it in the background, finds the address, generates a custom illustration, and saves the finished record itself. These agents can call the app's own methods too, so they can read existing data to decide what needs doing and write results straight back. Think about where this kind of enrichment would make a feature go from functional to magical.
|
|
14
|
-
- **Interfaces:** Web UI, REST API, cron jobs, webhooks, MCP tool servers, email processors, conversational AI agents — all backed by the same methods. An app can use any combination.
|
|
14
|
+
- **Interfaces:** Web UI, REST API, cron jobs, webhooks, MCP tool servers, email processors, conversational AI agents (text chat and realtime voice) — all backed by the same methods. An app can use any combination.
|
|
15
15
|
|
|
16
16
|
This is a capable, stable platform. Build with confidence; you're building production-grade apps, not fragile prototypes.
|
|
17
17
|
|
|
@@ -23,7 +23,7 @@ Don't recite this list to users. Use it to calibrate your sense of what's possib
|
|
|
23
23
|
- **AI-powered apps** — a document processor that extracts structured data from uploaded contracts, an AI image tool that transforms selfies into stylized portraits, a content generator that produces a week of social posts from one brief
|
|
24
24
|
- **Full-stack web apps** — social platforms, membership sites, marketplaces, booking systems, community hubs — multi-user apps with auth, data, UI
|
|
25
25
|
- **Automations** — cron jobs that monitor competitors and send alerts, webhook handlers that sync data between services, email processors that triage support requests — no UI needed
|
|
26
|
-
- **Conversational AI agents** — custom chat UIs backed by any model, with tool access to the app's methods. Full control over what the agent can do and who can use it
|
|
26
|
+
- **Conversational AI agents** — custom chat UIs backed by any model, with tool access to the app's methods. Full control over what the agent can do and who can use it. The same agents can also answer by realtime voice — a live, interruptible conversation with the app
|
|
27
27
|
- **Agent tools** — MCP tool servers for AI assistants
|
|
28
28
|
- **Creative projects** — browser games with p5.js or Three.js, interactive visualizations, 3D things, generative art, portfolio sites with dynamic backends
|
|
29
29
|
- **Marketing & launch pages** — landing pages, waitlist pages with referral mechanics, product sites with scroll animations — visual polish is a strength here
|