Agents

Structured Outputs

JSON mode and schema validation for predictable agent responses

Overview

Structured outputs ensure agents return data in predictable, machine-readable formats. This is essential for workflow automation, API integrations, and reliable data processing. Compozy provides JSON mode and JSON Schema validation to guarantee consistent output structures.

If you're new to structured outputs, start with our Quick Start Guide to understand basic workflow concepts, then explore Agent Configuration for foundational agent setup patterns.

JSON Mode

JSON mode forces agents to respond with valid JSON, enabling reliable parsing and processing of agent outputs. This is particularly valuable for multi-agent workflows where agent outputs become inputs for subsequent workflow tasks.

Enabling JSON Mode

JSON mode can be enabled at multiple levels, providing flexibility for different agent configurations and action patterns:

Enable JSON mode for all actions of an agent:

agents:
  - id: data-processor
    config:
      provider: openai
      model: gpt-4-turbo-preview
    json_mode: true  # All actions default to JSON
    instructions: |
      Always respond with valid JSON objects.

This approach works well when building specialized agents focused on data processing tasks.

JSON Mode Behavior

When JSON mode is enabled, agent behavior changes to ensure structured output compatibility:

  • Pure JSON Response: Agent must respond with valid JSON only
  • No Markdown: No markdown formatting or explanatory text outside JSON
  • Direct Parsing: Response is directly parseable by downstream workflow tasks
  • Validation Errors: Runtime errors occur if response isn't valid JSON

Output Schemas

Output schemas define the expected structure of agent responses using JSON Schema (Draft 7). Schemas provide validation, type safety, and clear contracts for agent interactions within workflow orchestration.

Basic Schema Definition

Define schemas directly within action definitions for simple validation:

actions:
  - id: classify-text
    prompt: "Classify the sentiment of the text"
    output:
      type: object
      properties:
        sentiment:
          type: string
          enum: ["positive", "negative", "neutral"]
          description: "Overall sentiment"
        confidence:
          type: number
          minimum: 0
          maximum: 1
          description: "Confidence score"
        keywords:
          type: array
          items:
            type: string
          description: "Key words indicating sentiment"
      required: ["sentiment", "confidence"]

This basic approach works well for simple schemas. For complex validation patterns, consider using reusable schemas to promote consistency across your workflow definitions.

Reusable Schemas

Define reusable schemas within your workflow to promote consistency and reduce duplication across multiple agents and actions. This approach leverages Compozy's $ref directive to reference schema definitions.

Defining Schemas

Add schema definitions to your workflow configuration under the schemas property:

# workflow.yaml
schemas:
  - id: user_profile
    type: object
    properties:
      email:
        type: string
        format: email
      name:
        type: string
        minLength: 2
      age:
        type: integer
        minimum: 0
        maximum: 150
    required: [email, name]

  - id: api_response
    type: object
    properties:
      status:
        type: string
        enum: [success, error, pending]
      data:
        type: object
      message:
        type: string
    required: [status]

  - id: classification_result
    type: object
    properties:
      category:
        type: string
      confidence:
        type: number
        minimum: 0
        maximum: 1
      metadata:
        type: object
    required: [category, confidence]

Referencing Schemas

Use the $ref directive to reference defined schemas in your agent actions:

Reference a schema by ID using local scope:

agents:
  - id: user-processor
    actions:
      - id: validate-user
        prompt: "Validate the user data structure"
        output:
          $ref: "local::schemas.#(id==\"user_profile\")"
      
      - id: classify-content
        prompt: "Classify the content type"
        output:
          $ref: "local::schemas.#(id==\"classification_result\")"

Schema Benefits

Reusable schemas provide several advantages for workflow development:

  • Consistency: Ensure uniform data structures across agents and actions
  • Maintainability: Update schema definitions in one place for project-wide changes
  • Validation: Leverage JSON Schema's powerful validation capabilities
  • Documentation: Schema descriptions serve as inline documentation for data structures
  • Integration: Seamless integration with YAML template system and workflow configuration

Practical Examples

Real-world examples demonstrating structured outputs in common scenarios. These patterns work well with parallel task execution and collection tasks for processing multiple data items efficiently.

Extract structured data from unstructured text using precise schemas:

schemas:
  - id: invoice_data
    type: object
    properties:
      invoice_number:
        type: string
        description: "Unique invoice identifier"
      date:
        type: string
        format: date
        description: "Invoice issue date in YYYY-MM-DD format"
      due_date:
        type: string
        format: date
      vendor:
        type: object
        properties:
          name:
            type: string
          address:
            type: string
          tax_id:
            type: string
      line_items:
        type: array
        items:
          type: object
          properties:
            description:
              type: string
            quantity:
              type: number
            unit_price:
              type: number
            total:
              type: number
      subtotal:
        type: number
      tax:
        type: number
      total:
        type: number
    required: ["invoice_number", "date", "vendor", "line_items", "total"]

agents:
  - id: invoice-processor
    actions:
      - id: extract-invoice
        prompt: |
          Extract invoice information from the text:
          {{.input.text}}

          Return all monetary values as numbers without currency symbols.
          Return dates in ISO 8601 format.
        json_mode: true
        output:
          $ref: "local::schemas.#(id==\"invoice_data\")"

This pattern works well for document processing workflows that need to extract and validate financial data.

Schema Validation Process

Understanding the validation lifecycle helps with debugging and building robust AI-powered workflows. Compozy validates schemas at multiple stages to ensure data integrity throughout the execution pipeline.

1

Pre-execution

Input schema validates incoming parameters. The input schema is applied to validate all incoming workflow parameters before execution begins, ensuring data integrity from the start. Failed validation prevents workflow execution and returns detailed error messages.
2

Agent Processing

Agent generates response following the schema. The agent processes the request with awareness of the output schema requirements, structuring its response accordingly. JSON mode is automatically enabled when output schemas are defined.
3

Post-execution

Output schema validates agent response. The generated response is validated against the defined output schema to ensure compliance with expected structure. This prevents malformed data from propagating to downstream tasks.
4

Error Handling

Validation errors are returned with details. Any validation failures produce detailed error messages with specific paths and expected values for debugging. Use these error messages to refine prompts or adjust schema definitions.

Validation Error Examples

Common validation scenarios and their error messages:

# Schema definition
output:
  type: object
  properties:
    score:
      type: number
      minimum: 0
      maximum: 100
  required: [score]

# Valid response ✅
{"score": 85}

# Invalid responses ❌
{"score": "high"}       # Error: expected number, got string
{"rating": 85}          # Error: missing required property 'score'
{"score": 150}          # Error: value exceeds maximum of 100

For advanced validation patterns and custom error handling, explore YAML Template Advanced Patterns and Error Handling in Workflows.

Advanced Topics

Integration Patterns

Learning Path