Structured Output

Get type-safe JSON responses from agents for API integration

Agents can return structured data - not just text. Define schemas, get validated JSON, build APIs. Perfect for data extraction, form filling, and programmatic access.

The Problem: Text Responses

Traditional agents return unstructured text:

User:  "Extract customer info from this email"
Agent: "The customer's name is John Smith, email is john@example.com,
        and phone is 555-0123."

Problem: How do you extract that data programmatically? - Parse with regex? (brittle) - Use another LLM call? (expensive) - String manipulation? (error-prone)

The Solution: Structured Output

Tell the agent what format you want:

response:
  format: json

Now you get:

{
  "name": "John Smith",
  "email": "john@example.com",
  "phone": "555-0123"
}

Machine-readable, type-safe, ready to use.

Response Formats

MUXI supports 4 response formats:

1. Markdown (Default)

response:
  format: markdown

Best for:

  • Documentation
  • Rich text with formatting
  • Human-readable content

Example output:

# Cloud Computing Benefits

## Cost Efficiency
- **Pay-as-you-use** pricing
- Reduced infrastructure costs

## Scalability
- Elastic resources
- Automatic scaling

2. Plain Text

response:
  format: text

Best for:

  • CLI applications
  • Log files
  • Simple integrations

Example output:

Cloud computing offers three key benefits:

1. Cost Efficiency
   Reduces infrastructure costs through pay-as-you-use pricing.

2. Scalability
   Provides elastic resources that grow with your needs.

3. JSON (Structured)

response:
  format: json

Best for:

  • REST APIs
  • Data extraction
  • Programmatic processing
  • Integration with JSON-based systems

Example output:

{
  "content": "Cloud computing offers cost efficiency, scalability, and global accessibility.",
  "type": "response",
  "format": "json"
}

4. HTML

response:
  format: html

Best for:

  • Web applications
  • Email templates
  • Content management systems

Example output:

<h1>Cloud Computing Benefits</h1>
<p>Key advantages include:</p>
<ul>
  <li><strong>Cost Efficiency:</strong> Pay-as-you-use pricing</li>
  <li><strong>Scalability:</strong> Elastic resources</li>
</ul>

How It Works

Format Instructions

MUXI adds format-specific instructions to the agent's prompt:

For JSON mode:
"Format your response as valid JSON. Use appropriate data structures
 (objects, arrays, strings, numbers, booleans) for the content."

For Plain Text:
"Format your response as plain text with no markdown, HTML, or special
 characters. Use simple line breaks and spacing only."

The agent naturally generates responses in the requested format.

Validation

JSON and HTML are validated:

  • JSON: Parsed with json.loads() - must be valid JSON
  • HTML: Validated with BeautifulSoup - proper tag structure

Markdown and Text are not validated (by design - more flexible).

Use Cases

Data Extraction

# Extract structured data from text
response:
  format: json

agents:
  - id: extractor
    system_message: |
      Extract customer information and return as JSON with fields:
      name, email, phone, company

Input: "John Smith from Acme Corp called, email john@acme.com, phone 555-0123"

Output:

{
  "name": "John Smith",
  "email": "john@acme.com",
  "phone": "555-0123",
  "company": "Acme Corp"
}

API Responses

from muxi import Muxi

client = Muxi()

# Request JSON format
response = client.chat(
    message="Analyze: " + text,
    format="json"
)

# response.content is already JSON!
return response.content
import { Muxi } from '@muxi/sdk';

const client = new Muxi();

// Request JSON format
const response = await client.chat({
  message: Analyze: ${text},
  format: 'json'
});

// response.content is already JSON!
return response.content;
import "github.com/muxi-ai/muxi-go"

client := muxi.NewClient()

// Request JSON format
response, _ := client.Chat(ctx, &muxi.ChatRequest{
    Message: "Analyze: " + text,
    Format:  "json",
})

// response.Content is already JSON!
return response.Content

Form Filling

response:
  format: json

agents:
  - id: form_filler
    system_message: |
      Fill out forms by extracting data from conversations.
      Return JSON matching the form schema.

User: "I want to sign up. I'm Alice Johnson, alice@example.com, in New York"

Output:

{
  "first_name": "Alice",
  "last_name": "Johnson",
  "email": "alice@example.com",
  "city": "New York"
}

Database Inserts

from muxi import Muxi
import json

client = Muxi()

# Extract data
response = client.chat(
    message="Extract product info from this description: ...",
    format="json"
)

# response.content is already JSON
product_data = json.loads(response.content)
db.insert("products", product_data)
import { Muxi } from '@muxi/sdk';

const client = new Muxi();

// Extract data
const response = await client.chat({
  message: 'Extract product info from this description: ...',
  format: 'json'
});

// response.content is already JSON
const productData = JSON.parse(response.content);
await db.insert('products', productData);
import (
    "encoding/json"
    "github.com/muxi-ai/muxi-go"
)

client := muxi.NewClient()

// Extract data
response, _ := client.Chat(ctx, &muxi.ChatRequest{
    Message: "Extract product info from this description: ...",
    Format:  "json",
})

// response.Content is already JSON
var productData map[string]interface{}
json.Unmarshal([]byte(response.Content), &productData)
db.Insert("products", productData)

Configuration

Formation-Wide Default

# formation.afs
overlord:
  response:
    format: json  # All responses are JSON

Runtime Override

from muxi import Muxi

client = Muxi()

# JSON format for this request
response1 = client.chat(message="Extract data...", format="json")

# Text format for this request
response2 = client.chat(message="Summarize...", format="text")
import { Muxi } from '@muxi/sdk';

const client = new Muxi();

// JSON format for this request
const response1 = await client.chat({ message: 'Extract data...', format: 'json' });

// Text format for this request
const response2 = await client.chat({ message: 'Summarize...', format: 'text' });
client := muxi.NewClient()

// JSON format for this request
response1, _ := client.Chat(ctx, &muxi.ChatRequest{Message: "Extract data...", Format: "json"})

// Text format for this request
response2, _ := client.Chat(ctx, &muxi.ChatRequest{Message: "Summarize...", Format: "text"})

Per-Request Format

# Via API
curl -X POST http://localhost:8001/v1/chat \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Extract customer info",
    "format": "json"
  }'

With Streaming

All formats work with streaming:

from muxi import Muxi

client = Muxi()

# Stream JSON response
for chunk in client.chat_stream(message="Analyze this...", format="json"):
    print(chunk.text, end="", flush=True)
import { Muxi } from '@muxi/sdk';

const client = new Muxi();

// Stream JSON response
for await (const chunk of client.chatStream({ message: 'Analyze this...', format: 'json' })) {
  process.stdout.write(chunk.text);
}
client := muxi.NewClient()

// Stream JSON response
stream, _ := client.ChatStream(ctx, &muxi.ChatRequest{
    Message: "Analyze this...",
    Format:  "json",
})
for chunk := range stream {
    fmt.Print(chunk.Text)
}

The agent streams the JSON as it's generated - collect chunks and parse at the end.

Best Practices

Clear Instructions

agents:
  - id: extractor
    system_message: |
      Extract information and return as JSON.
      Always include fields: name, email, phone, company.
      Use null for missing fields.

Clear instructions → better structured output.

Schema in Prompt

from muxi import Muxi
import json

client = Muxi()

schema = {
    "name": "string",
    "email": "string",
    "phone": "string | null",
    "company": "string | null"
}

response = client.chat(
    message=f"""Extract customer info. Return JSON matching this schema:
{json.dumps(schema, indent=2)}

Text: {input_text}""",
    format="json"
)
import { Muxi } from '@muxi/sdk';

const client = new Muxi();

const schema = {
  name: 'string',
  email: 'string',
  phone: 'string | null',
  company: 'string | null'
};

const response = await client.chat({
  message: ___CODE_SPAN_0___,
  format: 'json'
});

Providing schema improves accuracy.

Error Handling

import json

try:
    data = json.loads(response.content)
except json.JSONDecodeError:
    # Invalid JSON - retry or use fallback
    logger.error("Agent returned invalid JSON")
try {
  const data = JSON.parse(response.content);
} catch (e) {
  // Invalid JSON - retry or use fallback
  console.error('Agent returned invalid JSON');
}

Always validate, even with structured output.

Limitations

Not a Schema Validator

MUXI validates that JSON is valid, but doesn't enforce a specific schema:

// Agent might return this:
{"name": "John", "extra_field": "something"}

// Even if you only asked for name and email

Use Pydantic or JSON Schema validation if you need strict schema enforcement.

LLM Quality Dependent

Quality depends on:

  • LLM model capabilities
  • Prompt clarity
  • Input complexity

Better models (GPT-4, Claude) → better structured output.

Not Perfect

Agents may occasionally:

  • Return invalid JSON (rare with good models)
  • Include extra fields
  • Use unexpected data types

Always validate in production.

Why This Matters

Text Responses Structured Output
Parse with regex Use as-is
Fragile, breaks easily Robust, type-safe
Extra code needed Machine-readable
Hard to integrate API-ready
Unvalidated Validated format

The result: Agents that return data, not just text.

Quick Setup

# formation.afs
overlord:
  response:
    format: json  # or "text", "markdown", "html"

agents:
  - id: assistant
    system_message: |
      You are a helpful assistant.
      Return responses as valid JSON.

Learn More