growthxai avatar

output-meta-project-context

Comprehensive guide to Output.ai Framework for building durable, LLM-powered workflows orchestrated

by growthxai|Open Source

Output.ai Framework - Complete Project Context

What is Output.ai?

Output.ai provides infrastructure for building production-grade AI workflows: fact checkers, content generators, data extractors, research assistants, and multi-step agents. Built on Temporal, it guarantees durable execution - if execution fails mid-run, it resumes from the last successful step.

Core Philosophy

Separation of orchestration from I/O:

  • Workflows orchestrate execution (must be deterministic - no I/O)
  • Steps/Evaluators handle all I/O operations (HTTP, LLM, database calls)

This separation enables automatic retries, resumption, and debugging.

Component Taxonomy

ComponentPurposeKey Rule
WorkflowOrchestrates step executionMust be deterministic (no I/O, no Date.now(), no Math.random())
StepHandles all I/O operationsWhere HTTP, LLM, DB calls happen
EvaluatorQuality assessmentReturns confidence-scored results for validation loops
ScenarioTest input dataJSON files matching workflow's inputSchema
PromptLLM templatesLiquid.js templating with YAML frontmatter config
Eval TestOffline quality testingDataset-driven verification with verify() from @outputai/evals

Project Structure

config/
├── credentials.yml.enc          # Global encrypted credentials
├── credentials.key              # Global decryption key (DO NOT COMMIT)
└── credentials/                 # Environment-specific credentials
    ├── production.yml.enc
    └── production.key
src/
├── shared/                      # Shared code across workflows
│   ├── clients/                 # API clients (e.g., jina.ts, stripe.ts)
│   └── utils/                   # Utility functions (e.g., string.ts)
└── workflows/                   # Workflow definitions
    └── {workflow_name}/
        ├── workflow.ts          # Orchestration logic (deterministic)
        ├── steps.ts             # I/O operations
        ├── types.ts             # Zod schemas (input, output, internal)
        ├── evaluators.ts        # Quality checks (optional)
        ├── utils.ts             # Local utilities (optional)
        ├── credentials.yml.enc  # Workflow-specific credentials (optional)
        ├── prompts/             # LLM templates (optional)
        │   └── generate@v1.prompt
        ├── scenarios/           # Test inputs (optional)
        │   └── happy_path.json
        └── tests/               # Offline eval tests (optional)
            ├── datasets/        # YAML test datasets
            │   └── happy_path.yml
            └── evals/           # Eval evaluators and workflow
                ├── evaluators.ts
                └── workflow.ts

Code Reuse Rules

Shared directory (src/shared/):

  • shared/clients/ - API clients using @outputai/http for external services
  • shared/utils/ - Helper functions and utilities

Allowed imports:

  • Workflows/steps can import from ../../shared/clients/*.js and ../../shared/utils/*.js
  • Workflows/steps can import from local files (./types.js, ./utils.js)

Forbidden:

  • Importing from sibling workflow folders (../other_workflow/steps.js)
  • Steps importing other steps (activity isolation requirement)

Critical Rules

RuleCorrectIncorrect
Zod importimport { z } from '@outputai/core'import { z } from 'zod'
HTTP clientimport { httpClient } from '@outputai/http'import axios from 'axios'
Credentialsimport { credentials } from '@outputai/credentials'process.env.SECRET
LLM callsimport { generateText, Output } from '@outputai/llm'Direct provider SDK
ES importsimport { fn } from './file.js'import { fn } from './file'
Workflow I/OCall steps for any I/ODirect fetch/http in workflow

Determinism violations (never in workflows):

  • Date.now(), new Date()
  • Math.random(), crypto.randomUUID()
  • Direct HTTP/fetch calls
  • File system operations
  • Environment variable reads

Available Tools Inventory

Agents (5)

AgentPurpose
workflow-plannerDesigns workflow architecture, creates implementation blueprints
workflow-debuggerAnalyzes workflow execution traces, identifies issues
workflow-qualityReviews code quality, validates implementations
workflow-prompt-writerCreates and optimizes LLM prompt templates
workflow-context-fetcherGathers documentation and existing patterns

Commands (3)

CommandPurposeWhen to Use
/outputai:plan_workflowPlan workflow architectureALWAYS FIRST - creates implementation blueprint
/outputai:build_workflowBuild/implement workflowsAfter planning, or for modifications
/outputai:debug_workflowDebug workflow issuesWhen workflows fail or behave unexpectedly

Skills (29)

Workflow Operations (5)

SkillPurpose
output-workflow-runSynchronous workflow execution (waits for result)
output-workflow-startAsynchronous workflow execution (returns ID)
output-workflow-listList available workflows
output-workflow-statusCheck async workflow status
output-workflow-resultGet async workflow result

Monitoring & Debugging (4)

SkillPurpose
output-workflow-stopStop running workflow
output-workflow-traceTrace workflow execution
output-workflow-runs-listList workflow run history
output-services-checkVerify Output services status

Error Diagnosis (6)

SkillCatches
output-error-zod-importWrong zod import source
output-error-nondeterminismDate.now, Math.random in workflows
output-error-try-catchMissing error handling in steps
output-error-missing-schemasIncomplete Zod schema exports
output-error-direct-ioI/O operations in workflow files
output-error-http-clientUsing axios instead of @outputai/http

Meta/Lifecycle (3)

SkillPurpose
output-meta-pre-flightPre-operation validation checks
output-meta-post-flightPost-operation verification
output-meta-project-contextLoad full project context (this skill)

Development (11)

SkillPurpose
output-dev-folder-structureProject and workflow directory layout
output-dev-workflow-functionWriting deterministic workflow files
output-dev-step-functionWriting step functions for I/O
output-dev-types-fileZod schema definitions
output-dev-evaluator-functionQuality assessment functions
output-dev-eval-testingOffline eval tests with @outputai/evals
output-dev-prompt-fileLLM prompt templates with Liquid.js
output-dev-scenario-fileTest input JSON files
output-dev-http-client-createShared HTTP API client patterns
output-dev-credentialsEncrypted secrets management with @outputai/credentials
output-dev-create-skeletonGenerate workflow skeleton

CLI Quick Reference

# Development
npx output dev                              # Start dev environment

# List & inspect
npx output workflow list                    # List available workflows

# Execute
npx output workflow run <name> --input '{}'  # Run synchronously (waits)
npx output workflow start <name> --input '{}' # Run async (returns ID)
npx output workflow status <id>              # Check async status
npx output workflow result <id>              # Get async result

# Debug
npx output workflow debug <id>               # Debug failed workflow
npx output workflow debug <id> --format json # Machine-readable output

# Eval Testing
npx output workflow test <name>              # Run eval tests against datasets
npx output workflow test <name> --cached     # Use cached output (fast)
npx output workflow test <name> --save       # Run fresh and save results
npx output workflow dataset list <name>      # List datasets for a workflow
npx output workflow dataset generate <name> --input '{}'  # Generate dataset

# Credentials
output credentials init                      # Initialize encrypted credentials
output credentials edit                      # Edit credentials (decrypts, opens $EDITOR)
output credentials show                      # Show decrypted credentials
output credentials get <path>                # Get single credential value

Naming Conventions

ElementConventionExample
Workflow foldersnake_casefact_checker/
Workflow namesnake_casename: 'fact_checker'
Step functionscamelCasefetchArticle(), analyzeContent()
Schema namesPascalCaseInputSchema, ArticleData
Prompt filessnake_case@version.promptanalyze_claim@v1.prompt
Scenario filessnake_case.jsonhappy_path.json

Common Patterns

Workflow Pattern

import { workflow, z } from '@outputai/core';
import { fetchData, processData } from './steps.js';

export const inputSchema = z.object({ url: z.string().url() });
export const outputSchema = z.object({ result: z.string() });

export default workflow({
  name: 'my_workflow',
  description: 'Processes data from URL',
  inputSchema,
  outputSchema,
  fn: async (input) => {
    const data = await fetchData(input.url);
    const result = await processData(data);
    return { result };
  }
});

See output-dev-workflow-function for comprehensive patterns.

Step Pattern

import { step, z } from '@outputai/core';
import { httpClient } from '@outputai/http';

export const fetchData = step(
  { name: 'fetchData', inputSchema: z.string(), outputSchema: z.any() },
  async (url) => {
    const client = httpClient({ prefixUrl: url });
    const response = await client.get('');
    return response.json();
  }
);

See output-dev-step-function for comprehensive patterns.

HTTP Client Pattern (Shared)

Clients live in src/shared/clients/ and are shared across all workflows.

// src/shared/clients/example.ts
import { FatalError, ValidationError } from '@outputai/core';
import { httpClient } from '@outputai/http';
import { credentials } from '@outputai/credentials';

const API_KEY = credentials.require('example.api_key');

const client = httpClient({
  prefixUrl: 'https://api.example.com',
  headers: { Authorization: `Bearer ${API_KEY}` },
  timeout: 30000,
  retry: { limit: 3, statusCodes: [408, 429, 500, 502, 503, 504] }
});

export async function fetchFromExample(query: string): Promise<ExampleResponse> {

  try {
    const response = await client.get('endpoint', { searchParams: { q: query } });
    return response.json();
  } catch (error: unknown) {
    const err = error as { status?: number; message?: string };
    if (err.status === 401 || err.status === 403) {
      throw new FatalError(`Auth failed: ${err.message}`);
    }
    throw new ValidationError(`Request failed: ${err.message}`);
  }
}

Error type guidelines:

  • FatalError: 401, 403, 404 (won't succeed on retry)
  • ValidationError: 429, 5xx (may succeed on retry)

See output-dev-http-client-create for comprehensive patterns.

Evaluator Pattern

Evaluators return confidence-scored results. Three result types available:

import { evaluator, z, EvaluationBooleanResult, EvaluationNumberResult, EvaluationStringResult } from '@outputai/core';

// Boolean evaluator - pass/fail checks
export const evaluateCompleteness = evaluator({
  name: 'evaluate_completeness',
  description: 'Check if content meets minimum length',
  inputSchema: z.object({ content: z.string(), minLength: z.number() }),
  fn: async ({ content, minLength }) => {
    return new EvaluationBooleanResult({
      value: content.length >= minLength,
      confidence: 1.0,
      reasoning: `Content has ${content.length} chars (min: ${minLength})`
    });
  }
});

See output-dev-evaluator-function for comprehensive patterns.

Prompt File Pattern

Prompts use YAML frontmatter + Liquid.js templating. Location: src/workflows/{name}/prompts/

---
provider: anthropic
model: claude-sonnet-4
temperature: 0.7
maxTokens: 4096
---

<system>
You are an expert content analyzer.

{% if context %}
Additional context: {{ context }}
{% endif %}
</system>

<user>
Analyze the following content:

<content>
{{ content }}
</content>

Provide {{ numberOfPoints | default: 3 }} key insights.
</user>

Using in steps:

import { generateText, Output } from '@outputai/llm';
import { z } from '@outputai/core';

// Structured output
const { output } = await generateText({
  prompt: 'analyze@v1',
  variables: { content: 'Article text...', numberOfPoints: 5 },
  output: Output.object({
    schema: z.object({ insights: z.array(z.string()) })
  })
});

// Text output
const { result } = await generateText({
  prompt: 'summarize@v1',
  variables: { content: 'Article text...' }
});

Provider options:

ProviderModel Examples
anthropicclaude-sonnet-4, claude-opus-4
openaigpt-4o, gpt-4o-mini
vertexgemini-2.0-flash, gemini-2.5-pro

See output-dev-prompt-file for comprehensive patterns.


Practical Tips

Docker & Services

  • Restart worker after adding workflows: docker restart <project>-worker-1
  • View worker logs: docker logs -f output-worker-1
  • Check services: Use output-services-check skill

Payload Limits

  • Temporal: ~2MB per workflow input/output
  • gRPC: ~4MB maximum
  • For larger data, use file storage and pass references

Debugging Workflow Failures

  1. Get the workflow ID from error output
  2. Run npx output workflow debug <id> --format json
  3. Look for: failed step name, error message, input that caused failure
  4. Check if issue is determinism, schema validation, or external API
output-meta-project-context - AI Agent Skill for Claude Code & Cursor | Agent Skills