howone 0.1.23 → 0.1.25
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/package.json +1 -1
- package/templates/vite/.howone/skills/howone-sdk/01-architect/01-app-generation.md +180 -91
- package/templates/vite/.howone/skills/howone-sdk/01-architect/02-manifest-codegen.md +67 -4
- package/templates/vite/.howone/skills/howone-sdk/02-database/01-schema-design.md +463 -69
- package/templates/vite/.howone/skills/howone-sdk/02-database/02-schema-operations.md +366 -64
- package/templates/vite/.howone/skills/howone-sdk/02-database/03-data-access-patterns.md +204 -67
- package/templates/vite/.howone/skills/howone-sdk/02-database/04-query-dsl-and-responses.md +237 -0
- package/templates/vite/.howone/skills/howone-sdk/02-database/05-ai-persistence-patterns.md +372 -0
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/01-client-setup.md +58 -36
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/02-entity-operations.md +67 -0
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/03-auth.md +267 -469
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/04-react-integration.md +113 -320
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/07-ai-action-calls.md +66 -16
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/08-extension-boundaries.md +226 -0
- package/templates/vite/.howone/skills/howone-sdk/04-ai/01-ai-capability-architecture.md +159 -96
- package/templates/vite/.howone/skills/howone-sdk/04-ai/02-workflow-contract-rules.md +353 -96
- package/templates/vite/.howone/skills/howone-sdk/04-ai/03-ai-sdk-handoff.md +181 -42
- package/templates/vite/.howone/skills/howone-sdk/04-ai/04-service-capability-catalog.md +281 -0
- package/templates/vite/.howone/skills/howone-sdk/04-ai/05-workflow-operations.md +256 -0
- package/templates/vite/.howone/skills/howone-sdk/04-ai/06-ai-feature-playbooks.md +296 -0
- package/templates/vite/.howone/skills/howone-sdk/SKILL.md +29 -12
- package/templates/vite/.howone/skills/howone-sdk/agents/openai.yaml +2 -2
- package/templates/vite/package.json +1 -1
- package/templates/vite/.howone/skills/howone-sdk/04-ai/.gitkeep +0 -1
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# SDK Extension Boundaries
|
|
2
|
+
|
|
3
|
+
This reference defines the long-term shape of `@howone/sdk`. Use it whenever changing SDK APIs,
|
|
4
|
+
adding new capabilities, or deciding whether behavior belongs in the SDK or in the generated app.
|
|
5
|
+
|
|
6
|
+
## North Star
|
|
7
|
+
|
|
8
|
+
The SDK is an AI-first runtime, not an app UI framework.
|
|
9
|
+
|
|
10
|
+
It should provide:
|
|
11
|
+
|
|
12
|
+
- stable defaults that work with almost no configuration;
|
|
13
|
+
- typed clients for HowOne platform capabilities;
|
|
14
|
+
- adapters for custom behavior;
|
|
15
|
+
- callbacks/events for app UI;
|
|
16
|
+
- predictable names that AI agents can reuse without guessing.
|
|
17
|
+
|
|
18
|
+
It should not provide:
|
|
19
|
+
|
|
20
|
+
- app-owned pages, modals, toasts, or business UI;
|
|
21
|
+
- hardcoded app flows beyond HowOne platform defaults;
|
|
22
|
+
- hidden persistence side effects;
|
|
23
|
+
- provider-specific branches scattered through feature code.
|
|
24
|
+
|
|
25
|
+
## Default + Adapter Rule
|
|
26
|
+
|
|
27
|
+
Every platform capability should follow the same shape:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
createClient({
|
|
31
|
+
projectId,
|
|
32
|
+
env,
|
|
33
|
+
auth: 'hosted', // default
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Advanced usage should opt into typed adapters:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
createClient({
|
|
41
|
+
projectId,
|
|
42
|
+
env,
|
|
43
|
+
auth: {
|
|
44
|
+
mode: 'headless',
|
|
45
|
+
adapter: {
|
|
46
|
+
getToken: () => externalAuth.getToken(),
|
|
47
|
+
setToken: (token) => externalAuth.setToken(token),
|
|
48
|
+
login: ({ returnUrl }) => appRouter.push(`/login?redirect=${encodeURIComponent(returnUrl ?? '/')}`),
|
|
49
|
+
logout: () => appRouter.push('/'),
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Do not add one-off flags when an adapter/callback can express the behavior.
|
|
56
|
+
|
|
57
|
+
## Capability Boundaries
|
|
58
|
+
|
|
59
|
+
| Capability | SDK owns | App owns |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| Auth | token source, session state, login/logout destination policy, hosted HowOne defaults | login page visuals, account menu, loading states, auth error UI |
|
|
62
|
+
| React provider | context, auth callbacks, optional bottom-right HowOne `FloatingButton` logo | layout, toasts, overlays, route components, theme system |
|
|
63
|
+
| Entities | typed CRUD/query clients, public/private routing, payload normalization | forms, list rendering, optimistic UI, field-level UX |
|
|
64
|
+
| Schema | definition operations, preview/apply/version/restore calls | migration approval UI, admin experience |
|
|
65
|
+
| Entity contract utilities | payload whitelisting, public query guardrail validation, structured validation issues | deciding product copy, rendering validation errors |
|
|
66
|
+
| AI workflows | run/stream/events, Zod validation, workflowId binding | progress UI, result rendering, failure surfaces |
|
|
67
|
+
| AI persistence | pending-first orchestration helper, state callbacks, completed/failed mapping hook | choosing schema fields, retry UX, visible state UI |
|
|
68
|
+
| Upload | file/image/batch helpers and callbacks | picker UI, previews, validation copy, uploaded-file placement |
|
|
69
|
+
| Raw HTTP | low-level escape hatch | choosing it only when typed SDK surface does not exist |
|
|
70
|
+
|
|
71
|
+
## React Provider Boundary
|
|
72
|
+
|
|
73
|
+
`HowOneProvider` may render the HowOne bottom-right logo via `FloatingButton`. This is platform
|
|
74
|
+
branding and should remain visible by default.
|
|
75
|
+
|
|
76
|
+
It must not render:
|
|
77
|
+
|
|
78
|
+
- toast notifications;
|
|
79
|
+
- redirect overlays;
|
|
80
|
+
- login/register forms;
|
|
81
|
+
- payment dialogs;
|
|
82
|
+
- app theme wrappers;
|
|
83
|
+
- app-specific navigation.
|
|
84
|
+
|
|
85
|
+
Use callbacks instead:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
<HowOneProvider
|
|
89
|
+
auth="required"
|
|
90
|
+
brand="visible"
|
|
91
|
+
onAuthRedirect={({ mode, returnUrl }) => {
|
|
92
|
+
setAuthUi({ redirecting: true, mode, returnUrl })
|
|
93
|
+
}}
|
|
94
|
+
onAuthStateChange={(state) => {
|
|
95
|
+
setCurrentUser(state.user)
|
|
96
|
+
}}
|
|
97
|
+
>
|
|
98
|
+
<App />
|
|
99
|
+
</HowOneProvider>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Hide the logo only when explicitly requested:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<HowOneProvider brand="hidden" />
|
|
106
|
+
<HowOneProvider showBrandButton={false} />
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## UI Feedback Rule
|
|
110
|
+
|
|
111
|
+
Do not add `ClayxToast`, `toast`, or any visible notification API to `@howone/sdk`.
|
|
112
|
+
|
|
113
|
+
Generated apps should write their own UI from SDK results:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
setStatus({ type: 'loading', message: 'Generating...' })
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const output = await howone.ai.generateImage.run({ prompt })
|
|
120
|
+
setStatus({ type: 'success', message: 'Done', output })
|
|
121
|
+
} catch (error) {
|
|
122
|
+
setStatus({
|
|
123
|
+
type: 'error',
|
|
124
|
+
message: error instanceof Error ? error.message : 'Generation failed',
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
For streaming workflows, use callbacks/events:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const session = howone.ai.generateImage.stream(
|
|
133
|
+
{ prompt },
|
|
134
|
+
{
|
|
135
|
+
onStreamContent: (delta) => appendLog(delta),
|
|
136
|
+
onProgress: (progress) => setProgress(progress),
|
|
137
|
+
onError: (error) => setStatus({ type: 'error', message: error.message }),
|
|
138
|
+
onComplete: (result) => setResult(result.finalResult),
|
|
139
|
+
},
|
|
140
|
+
)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Auth Adapter Contract
|
|
144
|
+
|
|
145
|
+
Use `AuthAdapter` for custom/headless auth. It is the only supported extension point for token
|
|
146
|
+
ownership outside the SDK defaults.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
type AuthAdapter = {
|
|
150
|
+
name?: string
|
|
151
|
+
getToken?: () => string | null | Promise<string | null>
|
|
152
|
+
setToken?: (token: string | null) => void | Promise<void>
|
|
153
|
+
getUser?: (token: string | null) => AuthUser | null | Promise<AuthUser | null>
|
|
154
|
+
login?: (options?: { returnUrl?: string }) => void | Promise<void>
|
|
155
|
+
logout?: (options?: { redirect?: false | string | { url: string; external?: boolean } }) => void | Promise<void>
|
|
156
|
+
clearSession?: (options?: { redirect?: false | string | { url: string; external?: boolean } }) => void | Promise<void>
|
|
157
|
+
subscribe?: (listener: (state: AuthState) => void) => (() => void) | void
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Rules:
|
|
162
|
+
|
|
163
|
+
- Default hosted auth must work without an adapter.
|
|
164
|
+
- External providers must use `mode: 'headless'` plus `adapter`.
|
|
165
|
+
- Custom in-app HowOne login should usually use `mode: 'custom'`, `loginPath`, and SDK OTP/OAuth helpers.
|
|
166
|
+
- `client.me()` and `client.requireMe()` are the canonical user APIs.
|
|
167
|
+
- `client.auth.isAuthenticated()` is a quick token check, not a first-load user fetch.
|
|
168
|
+
|
|
169
|
+
## AI Agent Design Rules
|
|
170
|
+
|
|
171
|
+
Generated app code should have one stable SDK singleton:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import howone from '@/lib/sdk'
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Agents should prefer:
|
|
178
|
+
|
|
179
|
+
1. `howone.entities.*` for private/authenticated data;
|
|
180
|
+
2. `howone.public.entities.*` for public access;
|
|
181
|
+
3. `pickEntityPayload()` / `assertEntityPayload()` when mapping broad UI or AI objects to entity writes;
|
|
182
|
+
4. `assertPublicEntityQuery()` when generated code has access to the synced definition;
|
|
183
|
+
5. `howone.ai.*` for workflow execution;
|
|
184
|
+
6. `runAiActionAndPersist()` when the product needs durable AI history;
|
|
185
|
+
7. `howone.upload.*` for files;
|
|
186
|
+
8. `howone.schema.*` for schema tools;
|
|
187
|
+
9. `howone.raw` only as escape hatch.
|
|
188
|
+
|
|
189
|
+
Agents must not:
|
|
190
|
+
|
|
191
|
+
- hardcode HowOne URLs;
|
|
192
|
+
- manually build workflow SSE URLs;
|
|
193
|
+
- call workflows by display name instead of UUID;
|
|
194
|
+
- persist UI-only or workflow-extra fields;
|
|
195
|
+
- add frontend UI APIs to the SDK;
|
|
196
|
+
- remove the default HowOne floating logo unless explicitly asked.
|
|
197
|
+
|
|
198
|
+
## Adding New SDK Capabilities
|
|
199
|
+
|
|
200
|
+
When adding a new capability, choose one of these shapes:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
client.capability.method(input, options)
|
|
204
|
+
client.capability.stream(input, callbacks)
|
|
205
|
+
client.capability.configure(adapter)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Prefer these names:
|
|
209
|
+
|
|
210
|
+
- `run` for one-shot AI/workflow execution;
|
|
211
|
+
- `stream` for session-based execution with callbacks;
|
|
212
|
+
- `events` for async iterables;
|
|
213
|
+
- `query/list/get/create/update/delete` for entities;
|
|
214
|
+
- `configure` only for adapters, not app UI.
|
|
215
|
+
|
|
216
|
+
Keep returned values serializable and obvious. AI agents should be able to inspect the method name
|
|
217
|
+
and infer the contract.
|
|
218
|
+
|
|
219
|
+
## Compatibility Rule
|
|
220
|
+
|
|
221
|
+
Do not break existing generated apps lightly. Prefer:
|
|
222
|
+
|
|
223
|
+
- add new adapter/callback options;
|
|
224
|
+
- keep old string shorthand (`auth: 'custom'`) working;
|
|
225
|
+
- mark old UI props as deprecated/no-op only when needed;
|
|
226
|
+
- update this skill and the relevant numbered reference in the same change.
|
|
@@ -1,142 +1,205 @@
|
|
|
1
1
|
# AI Capability Architecture
|
|
2
2
|
|
|
3
|
-
Use this reference when a HowOne app needs AI generation, editing, analysis, research,
|
|
4
|
-
workflow-backed behavior.
|
|
3
|
+
Use this reference when a HowOne app needs AI generation, editing, analysis, research, media
|
|
4
|
+
creation, file generation, or any workflow-backed behavior.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
This file answers: **what AI layer should be designed, in what order, and where each responsibility
|
|
7
|
+
belongs?** For schema details read `02-workflow-contract-rules.md`. For workflow service calls read
|
|
8
|
+
`05-workflow-operations.md`.
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
## Platform Mental Model
|
|
9
11
|
|
|
10
|
-
|
|
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()`.
|
|
12
|
+
HowOne AI has five distinct layers:
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
| Layer | Owns | Does not own |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| Product feature | User-facing goal, UX states, persistence decision | workflow internals |
|
|
17
|
+
| AI capability contract | `name`, `description`, `inputSchema`, `outputSchema`, `outputEntityName`, versions, manifest | database CRUD, UI, auth |
|
|
18
|
+
| External workflow implementation | generated/edited workflow graph behind a `workflowId` | app schema, frontend state |
|
|
19
|
+
| Status/background layer | `request_id` polling, completed/failed state, `workflowConfigID` capture | SDK binding source |
|
|
20
|
+
| SDK binding/app code | `defineAiAction`, Zod schemas, `howone.ai.*`, persistence through entities | workflow generation |
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
Do not collapse these layers. The common mistakes are:
|
|
23
|
+
|
|
24
|
+
- putting database writes into the workflow;
|
|
25
|
+
- generating `src/lib/sdk.ts` before `.howone/ai/manifest.json` is synced;
|
|
26
|
+
- using action names instead of workflow UUIDs;
|
|
27
|
+
- treating workflow `outputSchema` as a database schema;
|
|
28
|
+
- faking unsupported AI with static frontend data.
|
|
29
|
+
|
|
30
|
+
## Source Of Truth
|
|
24
31
|
|
|
25
32
|
```text
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
user request = intent
|
|
34
|
+
agent AI contract proposal = draft
|
|
35
|
+
applied AI capability version = validated contract
|
|
36
|
+
.howone/ai/manifest.json = local synced source for SDK codegen
|
|
37
|
+
workflow service completed status = source for workflowConfigID
|
|
38
|
+
src/lib/sdk.ts = generated app binding
|
|
39
|
+
frontend UI = SDK consumer
|
|
40
|
+
entity schema = persistence contract, separate from AI contract
|
|
31
41
|
```
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
manifest. App code is generated from the manifest.
|
|
43
|
+
Never generate SDK bindings from the user prompt or from an unsynced draft.
|
|
35
44
|
|
|
36
|
-
## Standard AI Feature
|
|
45
|
+
## Standard AI Feature Flow
|
|
37
46
|
|
|
38
|
-
|
|
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.
|
|
47
|
+
Use this flow for new AI features:
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
1. Classify the feature using `04-ai/04-service-capability-catalog.md`.
|
|
50
|
+
2. Decide whether the feature is supported. If not supported, stop and explain the missing capability.
|
|
51
|
+
3. Decide one workflow per user-facing feature. Use two workflows only for RAG.
|
|
52
|
+
4. Design `inputSchema` and `outputSchema` using `02-workflow-contract-rules.md`.
|
|
53
|
+
5. Preview/apply the AI capability patch through the capability tool.
|
|
54
|
+
6. Sync `.howone/ai/manifest.json`.
|
|
55
|
+
7. Submit workflow create through `external-ai-capability` / workflow operate from the synced manifest.
|
|
56
|
+
8. Store returned `request_id` values for polling.
|
|
57
|
+
9. Poll status until `completed` or `failed`.
|
|
58
|
+
10. On completed + `payload.success === true`, store `payload.workflow_details.new_workflow_config_id`.
|
|
59
|
+
11. Generate/update `src/lib/sdk.ts` using `03-ai-sdk-handoff.md` and `01-architect/02-manifest-codegen.md`.
|
|
60
|
+
12. Implement UI calls through `howone.ai.<action>.run()`, `.stream()`, or `.events()`.
|
|
61
|
+
13. If output must persist, design entity schema and use `runAiActionAndPersist()` when appropriate.
|
|
52
62
|
|
|
53
|
-
|
|
63
|
+
Do not submit external workflow create/update from a hand-written schema. It should come from the
|
|
64
|
+
synced manifest.
|
|
54
65
|
|
|
55
|
-
|
|
56
|
-
available workflow service capabilities, stop the AI implementation task and report the gap.
|
|
66
|
+
## New Feature vs Existing Feature
|
|
57
67
|
|
|
58
|
-
|
|
68
|
+
| Situation | Correct path |
|
|
69
|
+
|---|---|
|
|
70
|
+
| New AI feature, no manifest entry | create AI capability, sync manifest, submit workflow create |
|
|
71
|
+
| Manifest entry exists but no workflow created yet | submit workflow create from manifest |
|
|
72
|
+
| User asks to change input/output contract | update capability contract first, sync, then submit workflow update |
|
|
73
|
+
| User asks to improve behavior only | submit workflow update with `workflowConfigID` and `updatePrompt` |
|
|
74
|
+
| User asks to save outputs/history | design/update database entity after AI output contract is known |
|
|
75
|
+
| User asks for public share of AI result | private history entity + public scoped share entity |
|
|
59
76
|
|
|
60
|
-
|
|
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.
|
|
77
|
+
## Create vs Update
|
|
66
78
|
|
|
67
|
-
|
|
68
|
-
missing or which rule blocks it, and what narrower supported alternative could be built.
|
|
79
|
+
Create external workflow when:
|
|
69
80
|
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
- capability has a `workflowId`;
|
|
82
|
+
- no confirmed external implementation exists;
|
|
83
|
+
- no `workflowConfigID` has been captured.
|
|
72
84
|
|
|
73
|
-
|
|
85
|
+
Update external workflow when:
|
|
86
|
+
|
|
87
|
+
- an external implementation exists;
|
|
88
|
+
- the status layer previously returned `payload.workflow_details.new_workflow_config_id`;
|
|
89
|
+
- you have a concrete `updatePrompt`.
|
|
74
90
|
|
|
75
|
-
|
|
76
|
-
The tool reads `workflowId`, `inputSchema`, `outputSchema`, and `outputEntityName` from the synced
|
|
77
|
-
manifest.
|
|
91
|
+
`workflowConfigID` is not the same as `workflowId`.
|
|
78
92
|
|
|
79
|
-
|
|
93
|
+
```text
|
|
94
|
+
workflowId = stable workflow UUID from manifest, used by SDK execution
|
|
95
|
+
workflowConfigID = implementation config ID from completed workflow generation/edit status
|
|
96
|
+
request_id = async operation ID returned by workflow operate endpoint
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Do not invent any of these IDs.
|
|
80
100
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
-
|
|
101
|
+
## Workflow Count Rule
|
|
102
|
+
|
|
103
|
+
Default: one user-facing AI feature equals one workflow.
|
|
104
|
+
|
|
105
|
+
Examples:
|
|
84
106
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
107
|
+
| Feature | Workflow count | Why |
|
|
108
|
+
|---|---:|---|
|
|
109
|
+
| Generate illustrated story | 1 | story text + images are one product action |
|
|
110
|
+
| Edit uploaded photo | 1 | one input image + edit prompt -> edited image |
|
|
111
|
+
| Research news briefing | 1 | search + synthesis are one action |
|
|
112
|
+
| Generate video from prompt | 1 | media generation is one action |
|
|
113
|
+
| Chat with uploaded documents | 2 | RAG needs indexing + query workflows |
|
|
88
114
|
|
|
89
|
-
|
|
90
|
-
|
|
115
|
+
Do not split normal multi-step behavior into separate workflows. The workflow service handles
|
|
116
|
+
internal orchestration.
|
|
91
117
|
|
|
92
118
|
## Persistence Boundary
|
|
93
119
|
|
|
94
|
-
AI workflows produce outputs. They do not
|
|
120
|
+
AI workflows produce outputs. They do not own product records.
|
|
95
121
|
|
|
96
|
-
Workflow
|
|
122
|
+
Workflow may do:
|
|
97
123
|
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
- financial or academic
|
|
102
|
-
-
|
|
124
|
+
- generate, summarize, translate, classify, extract;
|
|
125
|
+
- search/crawl and synthesize;
|
|
126
|
+
- generate/edit/analyze images, video, and audio;
|
|
127
|
+
- retrieve financial or academic data;
|
|
128
|
+
- save/read generated files through URL-based storage.
|
|
103
129
|
|
|
104
130
|
Workflow must not do:
|
|
105
131
|
|
|
106
|
-
- database create/read/update/delete
|
|
107
|
-
- authentication
|
|
108
|
-
- upload
|
|
109
|
-
- payment processing
|
|
110
|
-
-
|
|
111
|
-
-
|
|
132
|
+
- database create/read/update/delete;
|
|
133
|
+
- authentication/session logic;
|
|
134
|
+
- file upload from browser raw bytes;
|
|
135
|
+
- payment processing;
|
|
136
|
+
- owner assignment or permissions;
|
|
137
|
+
- app navigation, UI state, toast, or modal logic.
|
|
138
|
+
|
|
139
|
+
If the product needs durable history, use entity persistence outside the workflow:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
await runAiActionAndPersist({
|
|
143
|
+
entity: howone.entities.Generation,
|
|
144
|
+
input,
|
|
145
|
+
createPending: (input) => ({ prompt: input.prompt, status: 'pending' }),
|
|
146
|
+
run: (input) => howone.ai.generateImage.run(input),
|
|
147
|
+
mapCompleted: ({ output }) => ({ status: 'completed', resultUrl: output.generated_image_url }),
|
|
148
|
+
})
|
|
149
|
+
```
|
|
112
150
|
|
|
113
|
-
|
|
114
|
-
metadata such as prompt, selected options, status, timestamps, or references.
|
|
151
|
+
## Unsupported AI Behavior
|
|
115
152
|
|
|
116
|
-
|
|
153
|
+
If a user explicitly requires behavior not available in the workflow service, stop that AI path.
|
|
117
154
|
|
|
118
|
-
|
|
155
|
+
Do not:
|
|
119
156
|
|
|
120
|
-
|
|
157
|
+
- fake AI with static templates;
|
|
158
|
+
- hide the unsupported part;
|
|
159
|
+
- build a UI that pretends the workflow exists;
|
|
160
|
+
- replace the requested capability with a different one without saying so;
|
|
161
|
+
- assume private APIs, external datasets, or providers that are not listed.
|
|
162
|
+
|
|
163
|
+
Correct response:
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
This exact AI behavior needs <missing capability>. The current workflow service supports <closest
|
|
167
|
+
available capability>. I can build <narrow supported version>, or we need platform support for
|
|
168
|
+
<missing capability> first.
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Capability Naming
|
|
121
172
|
|
|
122
|
-
|
|
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.
|
|
173
|
+
Use stable JavaScript-safe IDs:
|
|
126
174
|
|
|
127
|
-
|
|
175
|
+
```text
|
|
176
|
+
generateIllustration
|
|
177
|
+
summarizeDocument
|
|
178
|
+
researchNewsBriefing
|
|
179
|
+
editProductPhoto
|
|
180
|
+
transcribeAudio
|
|
181
|
+
```
|
|
128
182
|
|
|
129
|
-
|
|
130
|
-
- query workflow: answers questions from the indexed knowledge base.
|
|
183
|
+
Avoid:
|
|
131
184
|
|
|
132
|
-
|
|
133
|
-
|
|
185
|
+
- display labels with spaces;
|
|
186
|
+
- names that collide with base methods: `run`, `stream`, `events`;
|
|
187
|
+
- provider names: `openAiImage`, `geminiAnalyze`;
|
|
188
|
+
- implementation names: `searchThenSummarize`.
|
|
134
189
|
|
|
135
|
-
|
|
190
|
+
The description can be human readable. The ID must be stable for codegen.
|
|
136
191
|
|
|
137
|
-
|
|
138
|
-
`summarizeDocument`. Do not use display labels as identifiers.
|
|
192
|
+
## AI Architecture Checklist
|
|
139
193
|
|
|
140
|
-
|
|
194
|
+
Before editing files:
|
|
141
195
|
|
|
142
|
-
|
|
196
|
+
- Feature maps to available workflow capabilities.
|
|
197
|
+
- One workflow per feature unless RAG.
|
|
198
|
+
- Description says what the user gets, not how tools run.
|
|
199
|
+
- Input schema accepts URLs for files, not raw bytes.
|
|
200
|
+
- Output schema contains only requested result fields.
|
|
201
|
+
- Input and output property names do not overlap.
|
|
202
|
+
- Text output descriptions specify language behavior.
|
|
203
|
+
- Persistence is modeled as entity schema, not workflow CRUD.
|
|
204
|
+
- `workflowId`, `request_id`, and `workflowConfigID` are not guessed.
|
|
205
|
+
- SDK binding will be generated only after manifest sync.
|