@output.ai/cli 0.8.1 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,435 +0,0 @@
1
- # Output.ai Based Project Guide
2
-
3
- ## Overview
4
-
5
- This project uses Output.ai Framework to build production-ready AI applications with built-in prompt management, evaluation, observability, and error handling. Developers use it to build AI features like fact checkers, content generators, data extractors, research assistants, and multi-step agents.
6
-
7
- ### Project Overview
8
-
9
- Each workflow lives in its own folder under `src/workflows/` and follows a consistent structure. Workflows define the orchestration logic, calling steps to perform external operations like API calls, database queries, and LLM inference. The framework automatically handles retries, timeouts, and reliable execution.
10
-
11
- ### Key Concepts
12
-
13
- #### Durable Execution powered by Temporal.io
14
-
15
- Output provides durable execution guarantees (built on Temporal.io) - if execution fails mid-run, it resumes from the last successful step rather than restarting. The framework provides high-level abstractions (`workflow`, `step`, `evaluator`) that enforce best practices and provide automatic tracing.
16
-
17
- #### Single Folder Project Structure
18
-
19
- Each workflow is self-contained in a single folder with a predictable structure: `workflow.ts` contains the deterministic orchestration logic, `steps.ts` contains I/O operations (API calls, LLM inference), `evaluators.ts` contains analysis logic returning confidence-scored results, and `prompts/*.prompt` files define LLM prompts using Liquid.js templates with YAML frontmatter for model configuration.
20
-
21
- ## Critical Conventions
22
-
23
- - **HTTP**: Never use axios → use `@output.ai/http` (traced, auto-retry)
24
- - **LLM**: Never call LLM APIs directly → use `@output.ai/llm`
25
- - **Workflows**: Must be deterministic - only call steps/evaluators, no direct I/O
26
- - **Steps**: All external operations (APIs, DBs, LLMs) must be wrapped in steps
27
- - **Schemas**: Use Zod (`z`) from `@output.ai/core` to define input/output schemas
28
-
29
- ## Code Reuse Rules
30
-
31
- **IMPORTANT: Workflows are isolated by design.** Do not reuse code directly between sibling workflows.
32
-
33
- ### Allowed Code Sharing Locations:
34
- - `src/clients/` - HTTP API clients shared across ALL workflows
35
- - `src/workflows/{name}/shared/` - Shared utilities within a workflow group
36
- - `src/workflows/{name}/lib/` - Internal libraries for a workflow group
37
-
38
- ### Forbidden:
39
- - Importing from sibling workflow folders (e.g., `../other_workflow/steps.js`)
40
- - Copying step implementations between workflows
41
- - Referencing types from other workflow folders
42
-
43
- Each workflow must remain independently deployable and testable. Cross-workflow imports create hidden dependencies that break this isolation.
44
-
45
- ## Project Structure
46
-
47
- ```
48
- src/
49
- clients/ # Shared HTTP API clients (one file per external service)
50
- jina.ts # Example: Jina Reader API client
51
- stripe.ts # Example: Stripe API client
52
- workflows/{name}/
53
- types.ts # Zod schemas and TypeScript types (should hold ALL types for the workflow)
54
- workflow.ts # Orchestration logic (deterministic)
55
- steps.ts # I/O operations (APIs, LLM, DB)
56
- evaluators.ts # LLM-as-a-judge analysis steps returning EvaluationResult
57
- prompts/*.prompt # LLM prompts (name@v1.prompt)
58
- scenarios/*.json # Test scenarios
59
- ```
60
-
61
- ## API Clients Pattern
62
-
63
- External API integrations should be placed in `src/clients/` as reusable modules. Each client wraps `@output.ai/http` for automatic tracing and retries.
64
-
65
- ```typescript
66
- // src/clients/jina.ts
67
- import { httpClient } from '@output.ai/http';
68
-
69
- const client = httpClient({
70
- prefixUrl: 'https://r.jina.ai',
71
- timeout: 30000
72
- });
73
-
74
- export const jinaClient = {
75
- read: async (url: string): Promise<string> => {
76
- const response = await client.get(url);
77
- return response.text();
78
- }
79
- };
80
- ```
81
-
82
- **Usage in steps:**
83
- ```typescript
84
- // src/workflows/my_workflow/steps.ts
85
- import { jinaClient } from '../../clients/jina.js';
86
-
87
- export const scrapeUrl = step({
88
- name: 'scrapeUrl',
89
- // ...
90
- fn: async (url) => jinaClient.read(url)
91
- });
92
- ```
93
-
94
- **Key requirements:**
95
- - One file per external service in `src/clients/`
96
- - Always use `@output.ai/http` (never axios or fetch directly)
97
- - Export a named client object with typed methods
98
- - Import clients in steps using relative paths (`../../clients/`)
99
-
100
- ## Types Pattern
101
-
102
- Every workflow MUST have a `types.ts` file containing all Zod schemas and TypeScript types. This ensures type safety and schema reusability across workflow components.
103
-
104
- ```typescript
105
- import { z } from '@output.ai/core';
106
-
107
- // Workflow input/output schemas
108
- export const WorkflowInputSchema = z.object({
109
- query: z.string().describe('The search query'),
110
- maxResults: z.number().optional().default(10)
111
- });
112
-
113
- export const WorkflowOutputSchema = z.object({
114
- results: z.array(z.object({
115
- title: z.string(),
116
- content: z.string()
117
- })),
118
- totalCount: z.number()
119
- });
120
-
121
- // Step schemas
122
- export const FetchDataInputSchema = z.object({
123
- url: z.string().url()
124
- });
125
-
126
- export const FetchDataOutputSchema = z.object({
127
- data: z.unknown(),
128
- status: z.number()
129
- });
130
-
131
- // Inferred TypeScript types
132
- export type WorkflowInput = z.infer<typeof WorkflowInputSchema>;
133
- export type WorkflowOutput = z.infer<typeof WorkflowOutputSchema>;
134
- export type FetchDataInput = z.infer<typeof FetchDataInputSchema>;
135
- export type FetchDataOutput = z.infer<typeof FetchDataOutputSchema>;
136
-
137
- // Shared interfaces (non-Zod types used within the workflow)
138
- export interface ApiResponse {
139
- code: number;
140
- data: unknown;
141
- }
142
- ```
143
-
144
- **Key requirements:**
145
- - All Zod schemas used in `workflow.ts` and `steps.ts` MUST be defined in `types.ts`
146
- - Export both schemas (for runtime validation) and inferred types (for TypeScript)
147
- - Use `.describe()` on schema fields for documentation
148
- - Keep API response interfaces separate from Zod schemas
149
-
150
- ## Commands
151
-
152
- ```bash
153
- npx output dev # Start dev (Temporal:8080, API:3001)
154
- npx output workflow list # List workflows
155
-
156
- # Sync execution (waits for result)
157
- npx output workflow run <name> --input <JSON|JSON_FILE> # Execute and wait
158
-
159
- # Async execution
160
- npx output workflow start <name> --input <JSON|JSON_FILE> # Start workflow, returns ID
161
- npx output workflow status <workflowId> # Check execution status
162
- npx output workflow result <workflowId> # Get result when complete
163
- npx output workflow stop <workflowId> # Cancel running workflow
164
- ```
165
-
166
- **When running workflows for users**: After execution completes, try to format the result nicely for readability. Use markdown formatting, tables for structured data, and highlight key values. Don't just dump raw JSON.
167
-
168
- ## Workflow Pattern
169
-
170
- Workflows orchestrate steps. They must be deterministic (no direct I/O).
171
-
172
- ```typescript
173
- import { workflow, z } from '@output.ai/core';
174
- import { processData, callApi } from './steps.js';
175
-
176
- export default workflow({
177
- name: 'my-workflow',
178
- description: 'What this workflow does',
179
- inputSchema: z.object({ query: z.string() }),
180
- outputSchema: z.object({ result: z.string() }),
181
- fn: async (input) => {
182
- const data = await processData(input);
183
- const result = await callApi(data);
184
- return { result };
185
- }
186
- });
187
- ```
188
-
189
- **Allowed imports**: steps.ts, evaluators.ts, ../../shared/steps/*.ts, types.ts, consts.ts, utils.ts
190
-
191
- **Forbidden in workflows**: Direct API calls, Math.random(), Date.now(), dynamic imports
192
-
193
- ## Step Pattern
194
-
195
- Steps contain all I/O operations. They are automatically retried on failure.
196
-
197
- ```typescript
198
- import { step, z } from '@output.ai/core';
199
- import { httpClient } from '@output.ai/http';
200
-
201
- const client = httpClient({ prefixUrl: 'https://api.example.com' });
202
-
203
- export const fetchData = step({
204
- name: 'fetchData',
205
- description: 'Fetch data from external API',
206
- inputSchema: z.object({ id: z.string() }),
207
- outputSchema: z.object({ data: z.any() }),
208
- fn: async ({ id }) => {
209
- const response = await client.get(`items/${id}`).json();
210
- return { data: response };
211
- },
212
- options: {
213
- retry: { maximumAttempts: 3 }
214
- }
215
- });
216
- ```
217
-
218
- ## LLM Pattern
219
-
220
- Use `@output.ai/llm` for all LLM operations. Prompts are defined in `.prompt` files.
221
-
222
- **Prompt file** (`summarize@v1.prompt`):
223
- ```yaml
224
- ---
225
- provider: anthropic
226
- model: claude-sonnet-4-20250514
227
- temperature: 0.7
228
- maxTokens: 2000
229
- ---
230
- <system>You are a helpful assistant.</system>
231
- <user>Summarize: {{ content }}</user>
232
- ```
233
-
234
- **Step using prompt**:
235
- ```typescript
236
- import { step, z } from '@output.ai/core';
237
- import { generateText, generateObject } from '@output.ai/llm';
238
-
239
- export const summarize = step({
240
- name: 'summarize',
241
- inputSchema: z.object({ content: z.string() }),
242
- outputSchema: z.string(),
243
- fn: async ({ content }) => {
244
- const { result } = await generateText({
245
- prompt: 'summarize@v1',
246
- variables: { content }
247
- });
248
- return result;
249
- }
250
- });
251
-
252
- // For structured output
253
- export const extractInfo = step({
254
- name: 'extractInfo',
255
- inputSchema: z.object({ text: z.string() }),
256
- outputSchema: z.object({ title: z.string(), summary: z.string() }),
257
- fn: async ({ text }) => {
258
- const { result } = await generateObject({
259
- prompt: 'extract@v1',
260
- variables: { text },
261
- schema: z.object({ title: z.string(), summary: z.string() })
262
- });
263
- return result;
264
- }
265
- });
266
- ```
267
-
268
- **Available functions**: `generateText`, `generateObject`, `generateArray`, `generateEnum`
269
-
270
- **Providers**: anthropic, openai, azure
271
-
272
- ## HTTP Pattern
273
-
274
- Use `@output.ai/http` for traced HTTP requests with automatic retry.
275
-
276
- ```typescript
277
- import { httpClient } from '@output.ai/http';
278
-
279
- const client = httpClient({
280
- prefixUrl: 'https://api.example.com',
281
- timeout: 30000,
282
- retry: { limit: 3 }
283
- });
284
-
285
- // In a step:
286
- const data = await client.get('endpoint').json();
287
- const result = await client.post('endpoint', { json: payload }).json();
288
- ```
289
-
290
- ## Evaluator Pattern
291
-
292
- Evaluators are LLM-as-a-judge for analyzing data and return confidence-scored results. They are highly recommended for anything that is high-value involving LLMs and can benefit from self-improvement loops or scoring for logging the results on tracing.
293
-
294
- ```typescript
295
- import { evaluator, EvaluationStringResult } from '@output.ai/core';
296
-
297
- export const judgeQuality = evaluator({
298
- name: 'judgeQuality',
299
- inputSchema: z.string(),
300
- fn: async (content) => {
301
- // Analysis logic
302
- return new EvaluationStringResult({
303
- value: 'good',
304
- confidence: 0.95
305
- });
306
- }
307
- });
308
- ```
309
-
310
- ## Error Handling
311
-
312
- ```typescript
313
- import { FatalError, ValidationError } from '@output.ai/core';
314
-
315
- // Non-retryable error (workflow fails immediately)
316
- throw new FatalError('Critical failure - do not retry');
317
-
318
- // Validation error (input/output schema failure)
319
- throw new ValidationError('Invalid input format');
320
- ```
321
-
322
- ## Creating New Workflows
323
-
324
- **IMPORTANT**: When creating a new workflow, you MUST use the following agents and commands in order. Do not skip steps.
325
-
326
- ### Mandatory Workflow Creation Process
327
-
328
- 1. **Plan** → `/outputai:plan_workflow` or `workflow-planner` agent
329
- - Defines workflow architecture, steps, and data flow
330
- - Identifies required external APIs and LLM operations
331
- - MUST be run first before any implementation
332
-
333
- 2. **Build** → `/outputai:build_workflow`
334
- - Creates the workflow folder structure
335
- - Generates `types.ts`, `workflow.ts`, `steps.ts`
336
- - Sets up test scenarios
337
-
338
- 3. **Prompts** → `workflow-prompt-writer` agent
339
- - Creates `.prompt` files for all LLM operations
340
- - Reviews and optimizes prompt templates
341
- - Ensures proper Liquid.js templating
342
-
343
- 4. **Quality** → `workflow-quality` agent
344
- - Validates implementation against best practices
345
- - Checks for proper error handling and retries
346
- - Ensures schema consistency across components
347
-
348
- ### Available Sub-Agents
349
-
350
- | Agent | Purpose |
351
- |-------|---------|
352
- | `workflow-planner` | Architecture design, step breakdown, data flow planning |
353
- | `workflow-prompt-writer` | Create and review `.prompt` files with proper templates |
354
- | `workflow-quality` | Validate best practices, error handling, schema consistency |
355
- | `workflow-context-fetcher` | Retrieve project context (used by other agents) |
356
- | `workflow-debugger` | Debug workflow issues, analyze execution traces |
357
-
358
- ### Available Commands
359
-
360
- | Command | When to Use |
361
- |---------|-------------|
362
- | `/outputai:plan_workflow` | **ALWAYS FIRST** - Plan new workflow architecture |
363
- | `/outputai:build_workflow` | Implement the planned workflow |
364
- | `/outputai:debug_workflow` | Debug failing or misbehaving workflows |
365
-
366
- ## Working with This Codebase
367
-
368
- **CRITICAL: Trust the documentation.** When creating or modifying workflows:
369
-
370
- 1. **Do NOT scan the entire codebase** - The patterns and examples in this document are authoritative
371
- 2. **Follow the documented patterns** - Use the step, workflow, and evaluator patterns exactly as shown
372
- 3. **Use the sub-agents** - They have the context needed to create correct implementations
373
-
374
- ### What to Read:
375
- - This current file (you're reading it)
376
- - The specific workflow folder you're modifying
377
- - `src/clients/` for available HTTP clients
378
-
379
- ### What NOT to Do:
380
- - Grep through all workflows looking for "examples"
381
- - Read multiple workflow implementations to "understand patterns"
382
- - Second-guess the documented patterns based on existing code variations
383
-
384
- ## Common Issues
385
-
386
- ### Restarting Worker After Adding Workflows
387
-
388
- After creating a new workflow, you likely need restart the worker container for changes to take effect.
389
-
390
- ```bash
391
- # Check running containers
392
- docker ps --filter "name=output" --format "\{{.Names}}: \{{.Status}}"
393
-
394
- # Restart the worker (adjust container name based on your project)
395
- docker restart <project-name>-worker-1
396
-
397
- # Wait for worker to restart, then run the workflow
398
- sleep 5 && npx output workflow run <workflow_name> --input '<json>'
399
- ```
400
-
401
- ### Payload Size Limits
402
-
403
- Plan for size limits when designing workflows.**
404
-
405
- - **Temporal limit**: ~2MB per workflow input/output payload
406
- - **gRPC limit**: ~4MB per message
407
-
408
- When planning workflows that process large data (documents, images, API responses):
409
- - Chunk large arrays and process in batches
410
- - Summarize or extract only needed fields from large API responses
411
- - When dealing with files prompt the user about cloud storage (S3, etc)
412
-
413
- ### Docker-Based Development
414
-
415
- `npx output dev` runs services in Docker containers. For debugging:
416
-
417
- ```bash
418
- # View worker logs
419
- docker logs -f output-worker-1
420
-
421
- # View API logs
422
- docker logs -f output-api-1
423
-
424
- # View Temporal logs
425
- docker logs -f output-temporal-1
426
-
427
- # Shell into a container
428
- docker exec -it output-worker-1 sh
429
- ```
430
-
431
- Logs do not appear in the terminal directly - check container logs when debugging workflow issues.
432
-
433
- ## Configuration
434
-
435
- See `.env` file for required environment variables (API keys, etc.)