howone 0.1.23 → 0.1.26

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 (36) hide show
  1. package/package.json +1 -1
  2. package/templates/vite/.howone/skills/howone/01-architect/01-app-generation.md +215 -0
  3. package/templates/vite/.howone/skills/{howone-sdk → howone}/01-architect/02-manifest-codegen.md +67 -4
  4. package/templates/vite/.howone/skills/howone/02-database/01-schema-design.md +541 -0
  5. package/templates/vite/.howone/skills/howone/02-database/02-schema-operations.md +398 -0
  6. package/templates/vite/.howone/skills/howone/02-database/03-data-access-patterns.md +309 -0
  7. package/templates/vite/.howone/skills/howone/02-database/04-query-dsl-and-responses.md +237 -0
  8. package/templates/vite/.howone/skills/howone/02-database/05-ai-persistence-patterns.md +372 -0
  9. package/templates/vite/.howone/skills/{howone-sdk → howone}/03-sdk/01-client-setup.md +58 -36
  10. package/templates/vite/.howone/skills/{howone-sdk → howone}/03-sdk/02-entity-operations.md +67 -0
  11. package/templates/vite/.howone/skills/howone/03-sdk/03-auth.md +414 -0
  12. package/templates/vite/.howone/skills/howone/03-sdk/04-react-integration.md +191 -0
  13. package/templates/vite/.howone/skills/{howone-sdk → howone}/03-sdk/07-ai-action-calls.md +168 -64
  14. package/templates/vite/.howone/skills/howone/03-sdk/08-extension-boundaries.md +226 -0
  15. package/templates/vite/.howone/skills/howone/04-ai/01-ai-capability-architecture.md +205 -0
  16. package/templates/vite/.howone/skills/howone/04-ai/02-workflow-contract-rules.md +426 -0
  17. package/templates/vite/.howone/skills/howone/04-ai/03-ai-sdk-handoff.md +234 -0
  18. package/templates/vite/.howone/skills/howone/04-ai/04-service-capability-catalog.md +281 -0
  19. package/templates/vite/.howone/skills/howone/04-ai/05-workflow-operations.md +256 -0
  20. package/templates/vite/.howone/skills/howone/04-ai/06-ai-feature-playbooks.md +296 -0
  21. package/templates/vite/.howone/skills/{howone-sdk → howone}/SKILL.md +29 -12
  22. package/templates/vite/.howone/skills/howone/agents/openai.yaml +4 -0
  23. package/templates/vite/package.json +1 -1
  24. package/templates/vite/.howone/skills/howone-sdk/01-architect/01-app-generation.md +0 -126
  25. package/templates/vite/.howone/skills/howone-sdk/02-database/01-schema-design.md +0 -147
  26. package/templates/vite/.howone/skills/howone-sdk/02-database/02-schema-operations.md +0 -96
  27. package/templates/vite/.howone/skills/howone-sdk/02-database/03-data-access-patterns.md +0 -172
  28. package/templates/vite/.howone/skills/howone-sdk/03-sdk/03-auth.md +0 -616
  29. package/templates/vite/.howone/skills/howone-sdk/03-sdk/04-react-integration.md +0 -398
  30. package/templates/vite/.howone/skills/howone-sdk/04-ai/.gitkeep +0 -1
  31. package/templates/vite/.howone/skills/howone-sdk/04-ai/01-ai-capability-architecture.md +0 -142
  32. package/templates/vite/.howone/skills/howone-sdk/04-ai/02-workflow-contract-rules.md +0 -169
  33. package/templates/vite/.howone/skills/howone-sdk/04-ai/03-ai-sdk-handoff.md +0 -80
  34. package/templates/vite/.howone/skills/howone-sdk/agents/openai.yaml +0 -4
  35. /package/templates/vite/.howone/skills/{howone-sdk → howone}/03-sdk/05-file-upload.md +0 -0
  36. /package/templates/vite/.howone/skills/{howone-sdk → howone}/03-sdk/06-raw-http.md +0 -0
@@ -1,398 +0,0 @@
1
- # React Integration
2
-
3
- ## What `@howone/sdk/react` Provides
4
-
5
- `@howone/sdk/react` is a **thin UI layer** for auth state, theme, and loading spinners. It does **not** provide entity, query, or AI data hooks.
6
-
7
- Exports:
8
- - `HowOneProvider` — all-in-one app provider (auth, theme, toasts, floating button)
9
- - `useHowoneContext` — access auth state (user, token, isAuthenticated, logout)
10
- - `FloatingButton` — a floating action button (shows Login when unauthenticated)
11
- - `Loading` — full-page or inline loading component
12
- - `LoadingSpinner` — headless spinner for composition
13
-
14
- ---
15
-
16
- ## Import
17
-
18
- ```ts
19
- import {
20
- HowOneProvider,
21
- useHowoneContext,
22
- FloatingButton,
23
- Loading,
24
- LoadingSpinner,
25
- } from '@howone/sdk/react'
26
- ```
27
-
28
- ---
29
-
30
- ## HowOneProvider
31
-
32
- Wrap your entire app. Provides auth, theme, and toast context to all children.
33
-
34
- `HowOneProvider` reads SDK environment and project defaults from `createClient`. Configure
35
- `projectId` and `env` once in `src/lib/sdk.ts`; do not pass a separate env to the provider.
36
-
37
- ```tsx
38
- // main.tsx or app/layout.tsx
39
- import React from 'react'
40
- import ReactDOM from 'react-dom/client'
41
- import { HowOneProvider } from '@howone/sdk/react'
42
- import './lib/sdk'
43
- import App from './App'
44
-
45
- ReactDOM.createRoot(document.getElementById('root')!).render(
46
- <React.StrictMode>
47
- <HowOneProvider
48
- auth="required"
49
- brand="visible"
50
- theme="system"
51
- >
52
- <App />
53
- </HowOneProvider>
54
- </React.StrictMode>
55
- )
56
- ```
57
-
58
- ### HowOneProviderProps
59
-
60
- ```ts
61
- type HowOneAuthMode = 'required' | 'optional' | 'none'
62
- type HowOneThemeMode = 'dark' | 'light' | 'system' | 'inherit'
63
- type HowOneBrandMode = 'visible' | 'hidden'
64
-
65
- interface HowOneProviderProps {
66
- children: React.ReactNode
67
-
68
- // Optional override. Prefer configuring projectId once in createClient.
69
- projectId?: string
70
-
71
- // Auth behaviour
72
- auth?: HowOneAuthMode
73
- // 'required' — redirects unauthenticated users to login page
74
- // 'optional' — allows both authenticated and unauthenticated users
75
- // 'none' — disables auth entirely
76
-
77
- // Brand button (HowOne branding)
78
- brand?: HowOneBrandMode // default: 'visible'
79
- showBrandButton?: boolean // alias for brand
80
-
81
- // Theme
82
- theme?: HowOneThemeMode // default: 'system'
83
- themeStorageKey?: string // localStorage key for theme preference
84
- forceTheme?: boolean // ignore user preference and force theme
85
- }
86
- ```
87
-
88
- ### Common provider configurations
89
-
90
- ```tsx
91
- // Public app — no auth required
92
- <HowOneProvider auth="none" theme="system" brand="hidden">
93
- <App />
94
- </HowOneProvider>
95
-
96
- // Auth-gated app — redirect to login if not authenticated
97
- <HowOneProvider auth="required" theme="system">
98
- <App />
99
- </HowOneProvider>
100
-
101
- // Optional auth — user can browse without logging in
102
- <HowOneProvider auth="optional" theme="inherit" brand="visible">
103
- <App />
104
- </HowOneProvider>
105
-
106
- // Dark mode forced
107
- <HowOneProvider auth="required" theme="dark" forceTheme>
108
- <App />
109
- </HowOneProvider>
110
- ```
111
-
112
- ---
113
-
114
- ## useHowoneContext
115
-
116
- Access auth state inside any component wrapped by `HowOneProvider`.
117
-
118
- ```ts
119
- type HowoneContextValue = {
120
- user: {
121
- id: string // backend owner id; same as userId when JWT has userId
122
- userId?: string // authenticated backend user id when present in JWT
123
- puid?: string // public UUID; do not use as public ownerId scope
124
- email: string
125
- name: string
126
- avatar: string
127
- appId?: string
128
- } | null
129
- token: string | null
130
- isAuthenticated: boolean
131
- logout: () => void
132
- }
133
- ```
134
-
135
- ### Usage
136
-
137
- ```tsx
138
- import { useHowoneContext } from '@howone/sdk/react'
139
-
140
- function UserMenu() {
141
- const { user, isAuthenticated, logout } = useHowoneContext()
142
-
143
- if (!isAuthenticated || !user) {
144
- return <a href="/login">Login</a>
145
- }
146
-
147
- return (
148
- <div>
149
- <img src={user.avatar} alt={user.name} />
150
- <span>{user.name}</span>
151
- <button onClick={logout}>Logout</button>
152
- </div>
153
- )
154
- }
155
- ```
156
-
157
- ### Conditional rendering based on auth state
158
-
159
- ```tsx
160
- function Dashboard() {
161
- const { isAuthenticated, user } = useHowoneContext()
162
-
163
- if (!isAuthenticated) {
164
- return <div>Please log in to continue.</div>
165
- }
166
-
167
- return <div>Welcome, {user?.name}!</div>
168
- }
169
- ```
170
-
171
- ### Using token for direct API calls
172
-
173
- ```tsx
174
- import { useHowoneContext } from '@howone/sdk/react'
175
-
176
- function DebugPanel() {
177
- const { token } = useHowoneContext()
178
-
179
- async function copyToken() {
180
- if (token) await navigator.clipboard.writeText(token)
181
- }
182
-
183
- return (
184
- <button onClick={copyToken} disabled={!token}>
185
- Copy JWT Token
186
- </button>
187
- )
188
- }
189
- ```
190
-
191
- ---
192
-
193
- ## FloatingButton
194
-
195
- A floating action button that renders in the bottom corner of the screen. When unauthenticated, it shows a "Login" label by default.
196
-
197
- ```tsx
198
- import { FloatingButton } from '@howone/sdk/react'
199
-
200
- // Default — shows Login/brand button
201
- <FloatingButton />
202
-
203
- // Custom text and handler
204
- <FloatingButton
205
- text="Get Started"
206
- onClick={() => router.push('/signup')}
207
- />
208
-
209
- // Custom styling
210
- <FloatingButton
211
- text="Support"
212
- onClick={() => setShowChat(true)}
213
- className="bg-blue-600 hover:bg-blue-700"
214
- />
215
- ```
216
-
217
- ### FloatingButtonProps
218
-
219
- ```ts
220
- interface FloatingButtonProps {
221
- text?: string // button label (default: 'Login' or brand text)
222
- onClick?: () => void
223
- className?: string // additional CSS classes
224
- }
225
- ```
226
-
227
- ---
228
-
229
- ## Loading Components
230
-
231
- ### Loading — full-page or inline loading state
232
-
233
- ```tsx
234
- import { Loading } from '@howone/sdk/react'
235
-
236
- // Full-screen overlay
237
- <Loading fullScreen label="Loading your workspace..." />
238
-
239
- // Inline with description
240
- <Loading
241
- label="Generating story..."
242
- description="This may take a moment"
243
- size="lg"
244
- tone="brand"
245
- />
246
-
247
- // Minimal
248
- <Loading />
249
- ```
250
-
251
- ### LoadingSpinner — headless spinner
252
-
253
- ```tsx
254
- import { LoadingSpinner } from '@howone/sdk/react'
255
-
256
- // Sizes: 'sm' | 'md' | 'lg'
257
- // Tones: 'brand' | 'neutral' | 'inverse'
258
-
259
- <LoadingSpinner size="md" tone="brand" />
260
- <LoadingSpinner size="sm" tone="neutral" className="mr-2" />
261
- ```
262
-
263
- ### LoadingProps
264
-
265
- ```ts
266
- type LoadingSize = 'sm' | 'md' | 'lg'
267
- type LoadingTone = 'brand' | 'neutral' | 'inverse'
268
-
269
- interface LoadingProps {
270
- size?: LoadingSize // default: 'md'
271
- tone?: LoadingTone // default: 'brand'
272
- label?: string // primary text
273
- description?: string // secondary text
274
- className?: string
275
- fullScreen?: boolean // renders over full viewport
276
- }
277
-
278
- interface LoadingSpinnerProps {
279
- size?: LoadingSize
280
- tone?: LoadingTone
281
- className?: string
282
- }
283
- ```
284
-
285
- ---
286
-
287
- ## Entity and AI Data in React
288
-
289
- `@howone/sdk/react` provides **no data hooks**. Use `useEffect`/`useState` or TanStack Query around the plain async SDK calls.
290
-
291
- ### Pattern: auth-gated data fetch
292
-
293
- ```tsx
294
- import { useEffect, useState } from 'react'
295
- import { useHowoneContext } from '@howone/sdk/react'
296
- import { Loading } from '@howone/sdk/react'
297
- import howone, { type StoryRecord } from '@/lib/sdk'
298
-
299
- function MyStories() {
300
- const { isAuthenticated } = useHowoneContext()
301
- const [stories, setStories] = useState<StoryRecord[]>([])
302
- const [loading, setLoading] = useState(false)
303
-
304
- useEffect(() => {
305
- if (!isAuthenticated) return
306
-
307
- setLoading(true)
308
- howone.entities.Story.query.mine({ page: { number: 1, size: 20 } })
309
- .then(result => setStories(result.items))
310
- .finally(() => setLoading(false))
311
- }, [isAuthenticated])
312
-
313
- if (!isAuthenticated) return <div>Please log in.</div>
314
- if (loading) return <Loading label="Loading your stories..." />
315
-
316
- return (
317
- <ul>
318
- {stories.map(s => <li key={s.id}>{s.title}</li>)}
319
- </ul>
320
- )
321
- }
322
- ```
323
-
324
- ### Pattern: Full app layout
325
-
326
- ```tsx
327
- // src/main.tsx
328
- import React from 'react'
329
- import ReactDOM from 'react-dom/client'
330
- import { HowOneProvider } from '@howone/sdk/react'
331
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
332
- import './lib/sdk'
333
- import App from './App'
334
-
335
- const queryClient = new QueryClient()
336
-
337
- ReactDOM.createRoot(document.getElementById('root')!).render(
338
- <React.StrictMode>
339
- <HowOneProvider
340
- auth="required"
341
- theme="system"
342
- brand="visible"
343
- >
344
- <QueryClientProvider client={queryClient}>
345
- <App />
346
- </QueryClientProvider>
347
- </HowOneProvider>
348
- </React.StrictMode>
349
- )
350
- ```
351
-
352
- ### Pattern: conditional AI action based on auth
353
-
354
- ```tsx
355
- import { useState } from 'react'
356
- import { useHowoneContext } from '@howone/sdk/react'
357
- import howone from '@/lib/sdk'
358
-
359
- function AIGenerateButton({ topic }: { topic: string }) {
360
- const { isAuthenticated } = useHowoneContext()
361
- const [loading, setLoading] = useState(false)
362
- const [result, setResult] = useState<string | null>(null)
363
-
364
- async function handleGenerate() {
365
- if (!isAuthenticated) {
366
- howone.auth.login()
367
- return
368
- }
369
- setLoading(true)
370
- try {
371
- const output = await howone.ai.generateStory.run({ topic, language: 'en' })
372
- setResult(output.content)
373
- } finally {
374
- setLoading(false)
375
- }
376
- }
377
-
378
- return (
379
- <div>
380
- <button onClick={handleGenerate} disabled={loading}>
381
- {loading ? 'Generating...' : isAuthenticated ? 'Generate' : 'Login to Generate'}
382
- </button>
383
- {result && <p>{result}</p>}
384
- </div>
385
- )
386
- }
387
- ```
388
-
389
- ---
390
-
391
- ## Common Mistakes
392
-
393
- | Mistake | Correct Pattern |
394
- |---|---|
395
- | `import { useHowoneContext } from '@howone/sdk'` | Import from `'@howone/sdk/react'` |
396
- | Expecting entity data hooks from `useHowoneContext` | Use `useEffect`/`useState` + `howone.entities.*` directly |
397
- | Placing `<HowOneProvider>` inside a component that re-renders | Place at root level (main.tsx / app layout) |
398
- | Using `user.id` without null-checking `user` | Guard: `if (!user) return` or use optional chaining `user?.id` |
@@ -1,142 +0,0 @@
1
- # AI Capability Architecture
2
-
3
- Use this reference when a HowOne app needs AI generation, editing, analysis, research, or other
4
- workflow-backed behavior.
5
-
6
- ## Core Split
7
-
8
- HowOne AI has four separate layers:
9
-
10
- 1. **Capability contract**: `ai-capability-design` owns the name, description, input schema, output
11
- schema, output entity name, workflow ID, versions, preview, apply, restore, and manifest sync.
12
- 2. **External workflow implementation**: `external-ai-capability` submits create/update operations
13
- to the workflow service using the synced contract from `.howone/ai/manifest.json`.
14
- 3. **Workflow status/background layer**: status checking, request tracking, completion, failure, and
15
- durable background-task behavior are handled outside the contract tool. Preserve request IDs and
16
- workflow config IDs for that layer.
17
- 4. **SDK binding and UI**: `src/lib/sdk.ts` is generated from `.howone/ai/manifest.json`, then the
18
- app calls `howone.ai.<capability>.run()`, `.stream()`, or `.events()`.
19
-
20
- Do not collapse these layers. The common failure is putting workflow implementation, persistence,
21
- and UI details into the capability schema.
22
-
23
- ## Source of Truth
24
-
25
- ```text
26
- agent proposal != source of truth
27
- applied AI capability version = source of truth
28
- .howone/ai/manifest.json = local source for codegen
29
- src/lib/sdk.ts = generated binding output
30
- external workflow service = implementation builder/editor
31
- ```
32
-
33
- The agent proposes a contract. The backend validates and versions it. The sync tool writes the
34
- manifest. App code is generated from the manifest.
35
-
36
- ## Standard AI Feature Workflow
37
-
38
- 1. Inspect current AI state with `ai-capability-design`.
39
- 2. Design one complete capability patch for the feature.
40
- 3. Preview the patch.
41
- 4. Apply the same operations.
42
- 5. Sync AI artifacts.
43
- 6. Read `.howone/ai/manifest.json`.
44
- 7. Submit external workflow create/update with `external-ai-capability`.
45
- 8. Preserve returned `requestIds` for the status/background-task layer.
46
- 9. Generate or update `src/lib/sdk.ts` from the manifest.
47
- 10. Implement UI calls through `howone.ai.*`.
48
- 11. If generated output must be stored, design database entities after the AI output schema exists.
49
-
50
- Do not preview a patch and then submit different operations. Do not restate schemas in
51
- `external-ai-capability`; it loads the manifest.
52
-
53
- ## Unsupported AI Requests
54
-
55
- If the user explicitly asks for AI capability and the feature cannot be implemented with the
56
- available workflow service capabilities, stop the AI implementation task and report the gap.
57
-
58
- Do not:
59
-
60
- - fake the AI feature with static mock data.
61
- - implement a frontend-only placeholder that pretends AI works.
62
- - design a workflow that assumes unavailable tools, providers, APIs, or private datasets.
63
- - silently drop the AI part and continue building a non-AI version.
64
- - move forbidden work such as database CRUD, auth, upload handling, payments, or app state into the
65
- workflow.
66
-
67
- The correct response is to state which requested AI behavior is unsupported, which capability is
68
- missing or which rule blocks it, and what narrower supported alternative could be built.
69
-
70
- Only continue implementation when the remaining feature still satisfies the user's intent after
71
- the unsupported AI capability is removed or narrowed.
72
-
73
- ## Create vs Update
74
-
75
- Use `external-ai-capability` with `mode: "create"` when a capability has no external implementation.
76
- The tool reads `workflowId`, `inputSchema`, `outputSchema`, and `outputEntityName` from the synced
77
- manifest.
78
-
79
- Use `mode: "update"` when the external workflow implementation needs to change. Updates require:
80
-
81
- - `capabilityName`
82
- - `workflowConfigID`
83
- - `updatePrompt`
84
-
85
- `workflowConfigID` must come from a confirmed workflow status result, specifically
86
- `payload.workflow_details.new_workflow_config_id`. Do not invent it, omit it, or substitute
87
- `workflowId`.
88
-
89
- If the input/output schema changes, update the capability contract first, sync the manifest, then
90
- submit the external workflow update.
91
-
92
- ## Persistence Boundary
93
-
94
- AI workflows produce outputs. They do not persist app state.
95
-
96
- Workflow can do:
97
-
98
- - text generation, summarization, translation, classification, extraction
99
- - image, video, and audio generation/editing/analysis
100
- - web research and page crawling
101
- - financial or academic retrieval
102
- - file generation or file reading through URLs
103
-
104
- Workflow must not do:
105
-
106
- - database create/read/update/delete
107
- - authentication or session handling
108
- - upload handling
109
- - payment processing
110
- - app state management
111
- - owner assignment or record permissions
112
-
113
- If the app saves AI output, derive entity fields from `outputSchema` and add only necessary request
114
- metadata such as prompt, selected options, status, timestamps, or references.
115
-
116
- ## Workflow Count
117
-
118
- Default rule: one user-facing AI feature maps to one capability and one workflow.
119
-
120
- Examples:
121
-
122
- - Story + illustration generator: one workflow that returns story text and generated image URLs.
123
- - Image edit feature: one workflow that accepts source image URL and edit instruction, returns
124
- edited image URL.
125
- - News briefing: one workflow that searches and summarizes, returns briefing and source links.
126
-
127
- RAG is the exception:
128
-
129
- - indexing workflow: ingests documents and creates retrieval/indexing artifacts.
130
- - query workflow: answers questions from the indexed knowledge base.
131
-
132
- Do not split normal sequential AI steps into multiple capabilities unless they are independently
133
- triggered product features.
134
-
135
- ## Capability Naming
136
-
137
- Use stable JavaScript-safe identifiers for capability names, for example `generateIllustration` or
138
- `summarizeDocument`. Do not use display labels as identifiers.
139
-
140
- Avoid names that collide with action methods: `run`, `stream`, `events`.
141
-
142
- Use `outputEntityName` only when the generated output has a natural persisted record shape.
@@ -1,169 +0,0 @@
1
- # Workflow Contract Rules
2
-
3
- Use this reference when designing `inputSchema`, `outputSchema`, and capability descriptions for
4
- HowOne AI workflows.
5
-
6
- ## Loose JSON Schema
7
-
8
- Workflow schemas should be loose enough for an AI workflow engine.
9
-
10
- Rules:
11
-
12
- - Require only essential inputs.
13
- - Mark non-essential options optional.
14
- - Prefer `string` with a clear description over restrictive enums when user values are open-ended.
15
- - Avoid `minLength`, `maxLength`, `pattern`, and narrow validation unless there is a concrete
16
- technical reason.
17
- - Avoid nested objects when a simple described string is enough.
18
- - Avoid exposing implementation knobs the user does not need.
19
-
20
- Good:
21
-
22
- ```json
23
- {
24
- "tone": {
25
- "type": "string",
26
- "description": "Desired writing tone, e.g. formal, casual, humorous, empathetic, professional."
27
- }
28
- }
29
- ```
30
-
31
- Use enums only for truly closed domains.
32
-
33
- ## URLs, Not Raw Files
34
-
35
- All file exchange uses URLs.
36
-
37
- Rules:
38
-
39
- - File inputs are strings with `format: "uri"`, such as `document_url`, `source_image_url`, or
40
- `audio_file_url`.
41
- - File outputs are strings with `format: "uri"`, such as `generated_image_url`, `edited_video_url`,
42
- or `result_pdf_url`.
43
- - Never use base64, raw bytes, inline file content, or `contentEncoding`.
44
- - The app uploads user files first, then passes the URL to the workflow.
45
-
46
- ## Output Minimalism
47
-
48
- The workflow will try to fill every output field. Only ask for fields the product needs.
49
-
50
- Usually forbidden unless explicitly requested:
51
-
52
- - timestamps and processing time
53
- - file size, MIME type, encoding, dimensions, frame rate, bitrate
54
- - confidence scores and bounding boxes
55
- - model, provider, version, cost, or internal execution metadata
56
- - style/tone metadata when the user only asked for an asset
57
-
58
- Examples:
59
-
60
- | User Need | Good Output | Avoid |
61
- |---|---|---|
62
- | Summarize a document | `summary` | `summary`, `word_count`, `reading_time` |
63
- | Generate an image | `generated_image_url` | `generated_image_url`, `model_used`, `color_palette` |
64
- | OCR an image | `extracted_text` | `extracted_text`, `confidence_score`, `bounding_boxes` |
65
-
66
- ## No Input/Output Name Overlap
67
-
68
- Input and output property names must not overlap. The workflow engine uses a shared parameter
69
- namespace.
70
-
71
- Bad:
72
-
73
- ```json
74
- {
75
- "inputSchema": { "properties": { "text": { "type": "string" } } },
76
- "outputSchema": { "properties": { "text": { "type": "string" } } }
77
- }
78
- ```
79
-
80
- Good:
81
-
82
- ```json
83
- {
84
- "inputSchema": { "properties": { "source_text": { "type": "string" } } },
85
- "outputSchema": { "properties": { "translated_text": { "type": "string" } } }
86
- }
87
- ```
88
-
89
- Common pairs:
90
-
91
- - `source_text` -> `translated_text`
92
- - `source_content` -> `summary`
93
- - `source_image_url` -> `edited_image_url`
94
- - `description_prompt` -> `generated_image_url`
95
-
96
- ## Output Language
97
-
98
- Every text output field description must specify the language rule.
99
-
100
- Use one of these patterns:
101
-
102
- - fixed: "Summary in English."
103
- - input-driven: "Translated text in the target language specified by `target_language`."
104
- - source-driven: "Summary in the same language as the source document."
105
- - mixed: "Extracted text, which may contain mixed Chinese and English content."
106
-
107
- Do not write vague descriptions like "The translated text."
108
-
109
- ## Description Says What, Not How
110
-
111
- `capability.description` describes the user outcome.
112
-
113
- Do:
114
-
115
- ```json
116
- {
117
- "description": "Searches the web for the latest news on a topic and produces a structured briefing with source links."
118
- }
119
- ```
120
-
121
- Do not:
122
-
123
- ```json
124
- {
125
- "description": "First calls search_web, then summarizes each article with an LLM, then saves JSON."
126
- }
127
- ```
128
-
129
- Never mention internal tool names, step sequences, providers, or model names in the capability
130
- description.
131
-
132
- ## Available Capability Families
133
-
134
- Design only around capabilities available to the workflow service:
135
-
136
- - web search and page crawling
137
- - image generation, editing, analysis, OCR
138
- - video generation, editing, concatenation, frame extraction
139
- - audio generation, recognition, merging
140
- - financial price history retrieval
141
- - academic paper search and bibliography
142
- - file storage/read for JSON, YAML, CSV, PDF, Markdown, TXT
143
- - email sending
144
- - RSS feed fetching
145
- - Airbnb search
146
- - Hacker News search
147
-
148
- If the requested product needs unavailable functionality, redesign the feature around available
149
- capabilities or exclude it explicitly.
150
-
151
- When the user explicitly requires the unavailable AI behavior, terminate the AI task instead of
152
- building a fake or silently degraded implementation. Report the unsupported requirement and the
153
- closest supported alternative.
154
-
155
- ## External Data Assumptions
156
-
157
- Do not assume the user can provide external datasets unless they explicitly say so.
158
-
159
- For "stock analysis", use a workflow input such as `trading_symbol` and let the workflow retrieve
160
- history. Do not require `stock_data_csv_url` unless the user says they have a CSV.
161
-
162
- For "latest news", use web search inside the workflow. Do not ask the user to provide article URLs
163
- unless that is the product requirement.
164
-
165
- ## MVP Limit
166
-
167
- Keep AI app generation to at most five core features. Exclude feedback forms, onboarding tutorials,
168
- notification settings, export, sharing, personalization, and preferences unless the user explicitly
169
- requests them.