A module for the Loopstack AI automation framework.
This module provides an example workflow demonstrating how to generate structured output from an LLM using a custom document schema.
The Prompt Structured Output Example Workflow shows how to use the aiGenerateDocument tool to get structured, typed responses from an LLM. It generates a "Hello, World!" script in a user-selected programming language, with the response structured into filename, description, and code fields.
By using this workflow as a reference, you'll learn how to:
- Define custom document schemas with Zod for structured LLM output
- Use the
aiGenerateDocumenttool to generate typed responses - Create custom documents with form configuration
- Store structured data in workflow state using
@WithState
This example builds on the basic prompt pattern and is ideal for developers who need typed, structured responses from LLMs.
Create a new Loopstack project if you haven't already:
npx create-loopstack-app my-project
cd my-projectStart Environment
cd my-project
docker compose up -dloopstack add @loopstack/prompt-structured-output-example-workflowThis copies the source files into your src directory.
Using the
loopstack addcommand is a great way to explore the code to learn new concepts or add own customizations.
Add PromptStructuredOutputExampleModule to your default.module.ts (included in the skeleton app) or to your own module:
import { Module } from '@nestjs/common';
import { LoopCoreModule } from '@loopstack/core';
import { CoreUiModule } from '@loopstack/core-ui-module';
import { AiModule } from '@loopstack/ai-module';
import { DefaultWorkspace } from './default.workspace';
import { PromptStructuredOutputExampleModule } from './@loopstack/prompt-structured-output-example-workflow';
@Module({
imports: [LoopCoreModule, PromptStructuredOutputExampleModule],
providers: [DefaultWorkspace],
})
export class DefaultModule {}Add the workflow to your workspace class using the @Workflow() decorator:
import { Injectable } from '@nestjs/common';
import { BlockConfig, Workflow } from '@loopstack/common';
import { WorkspaceBase } from '@loopstack/core';
import { PromptStructuredOutputWorkflow } from './@loopstack/prompt-structured-output-example-workflow';
@Injectable()
@BlockConfig({
config: {
title: 'My Workspace',
description: 'A workspace with the structured output example workflow',
},
})
export class MyWorkspace extends WorkspaceBase {
@Workflow() promptStructuredOutputWorkflow: PromptStructuredOutputWorkflow;
}Set your OpenAI API key as an environment variable:
OPENAI_API_KEY=sk-...Define a Zod schema for the structured output:
export const FileDocumentSchema = z.object({
filename: z.string(),
description: z.string().optional(),
code: z.string(),
});Create a document class that uses this schema:
@Injectable()
@BlockConfig({
configFile: __dirname + '/file-document.yaml',
})
@WithArguments(FileDocumentSchema)
export class FileDocument extends DocumentBase {}Configure how the document is displayed in the UI:
type: document
ui:
form:
order:
- filename
- description
- code
properties:
filename:
title: File Name
readonly: true
description:
title: Description
readonly: true
code:
title: Code
widget: code-viewUse Zod enums to provide a dropdown selection in the UI:
@WithArguments(z.object({
language: z.enum(['python', 'javascript', 'java', 'cpp', 'ruby', 'go', 'php']).default('python'),
}))Configure the select widget in YAML:
ui:
form:
properties:
language:
title: 'What programming language should the script be in?'
widget: selectUse aiGenerateDocument with a response.document to get typed output:
- tool: aiGenerateDocument
args:
llm:
provider: openai
model: gpt-4o
response:
document: fileDocument
prompt: |
Create a {{ args.language }} script that prints 'Hello, World!' to the console.
Wrap the code in triple-backticks.
assign:
file: ${ result.data.content }The LLM response is automatically parsed into the FileDocument schema.
Use @WithState to define typed state that persists across transitions:
@WithState(z.object({
file: FileDocumentSchema,
}))Access state values in subsequent transitions:
text: |
Successfully generated: {{ file.description }}This workflow uses the following Loopstack modules:
@loopstack/core- Core framework functionality@loopstack/core-ui-module- ProvidesCreateDocumenttool@loopstack/ai-module- ProvidesAiGenerateDocumenttool andAiMessageDocument
Author: Jakob Klippel
License: Apache-2.0
- Loopstack Documentation
- Getting Started with Loopstack
- Find more Loopstack examples in the Loopstack Registry