Tools Guide
Combine structured output with tool calling. Tools →
Structured output ensures model responses conform to a specific format, making them easier to parse and integrate into applications. Iris provides two modes: JSON mode for freeform valid JSON, and JSON Schema mode for strict schema enforcement.
JSON mode instructs the model to output valid JSON without enforcing a specific structure. Use this when you need valid JSON but want flexibility in the response format.
package main
import ( "context" "encoding/json" "fmt" "os"
"github.com/petal-labs/iris/core" "github.com/petal-labs/iris/providers/openai")
func main() { provider := openai.New(os.Getenv("OPENAI_API_KEY")) client := core.NewClient(provider) ctx := context.Background()
resp, err := client.Chat("gpt-4o-mini"). System("You are a helpful assistant that responds in JSON format."). User("List 3 programming languages with their name, year created, and creator."). ResponseJSON(). GetResponse(ctx)
if err != nil { panic(err) }
fmt.Println("Raw JSON:") fmt.Println(resp.Output)
// Parse the response var result struct { Languages []struct { Name string `json:"name"` Year int `json:"year"` Creator string `json:"creator"` } `json:"languages"` }
if err := json.Unmarshal([]byte(resp.Output), &result); err != nil { panic(err) }
fmt.Println("\nParsed:") for _, lang := range result.Languages { fmt.Printf(" %s (%d) by %s\n", lang.Name, lang.Year, lang.Creator) }}Output:
Raw JSON:{"languages": [{"name": "Go", "year": 2009, "creator": "Robert Griesemer, Rob Pike, Ken Thompson"}, ...]}
Parsed: Go (2009) by Robert Griesemer, Rob Pike, Ken Thompson Python (1991) by Guido van Rossum Rust (2010) by Graydon HoareJSON Schema mode enforces a strict schema on the model output. The model is guaranteed to produce JSON that validates against your schema, including required fields and type constraints.
package main
import ( "context" "encoding/json" "fmt" "os"
"github.com/petal-labs/iris/core" "github.com/petal-labs/iris/providers/openai")
// Define your Go typestype Person struct { Name string `json:"name"` Age int `json:"age"` Occupation string `json:"occupation"` Hobbies []string `json:"hobbies"`}
func main() { provider := openai.New(os.Getenv("OPENAI_API_KEY")) client := core.NewClient(provider) ctx := context.Background()
// Define the JSON Schema schema := &core.JSONSchemaDefinition{ Name: "person_info", Description: "Information about a person", Strict: true, Schema: json.RawMessage(`{ "type": "object", "properties": { "name": { "type": "string", "description": "The person's full name" }, "age": { "type": "integer", "description": "The person's age in years" }, "occupation": { "type": "string", "description": "The person's job or profession" }, "hobbies": { "type": "array", "items": {"type": "string"}, "description": "List of hobbies" } }, "required": ["name", "age", "occupation", "hobbies"], "additionalProperties": false }`), }
resp, err := client.Chat("gpt-4o-mini"). User("Extract information: Sarah is a 28-year-old software engineer who enjoys hiking, reading, and playing chess."). ResponseJSONSchema(schema). GetResponse(ctx)
if err != nil { panic(err) }
// Parse directly into Go struct var person Person if err := json.Unmarshal([]byte(resp.Output), &person); err != nil { panic(err) }
fmt.Printf("Name: %s\n", person.Name) fmt.Printf("Age: %d\n", person.Age) fmt.Printf("Occupation: %s\n", person.Occupation) fmt.Printf("Hobbies: %v\n", person.Hobbies)}Output:
Name: SarahAge: 28Occupation: software engineerHobbies: [hiking reading playing chess]When using strict mode (Strict: true), your schema must follow these rules:
required arrayadditionalProperties: falsestring, number, integer, boolean, array, object, nulloneOf, anyOf, not, patternPropertiesschema := &core.JSONSchemaDefinition{ Name: "order", Strict: true, Schema: json.RawMessage(`{ "type": "object", "properties": { "order_id": {"type": "string"}, "customer": { "type": "object", "properties": { "name": {"type": "string"}, "email": {"type": "string"} }, "required": ["name", "email"], "additionalProperties": false }, "items": { "type": "array", "items": { "type": "object", "properties": { "product": {"type": "string"}, "quantity": {"type": "integer"}, "price": {"type": "number"} }, "required": ["product", "quantity", "price"], "additionalProperties": false } }, "total": {"type": "number"} }, "required": ["order_id", "customer", "items", "total"], "additionalProperties": false }`),}schema := &core.JSONSchemaDefinition{ Name: "ticket", Strict: true, Schema: json.RawMessage(`{ "type": "object", "properties": { "title": {"type": "string"}, "priority": { "type": "string", "enum": ["low", "medium", "high", "critical"] }, "status": { "type": "string", "enum": ["open", "in_progress", "resolved", "closed"] }, "tags": { "type": "array", "items": {"type": "string"} } }, "required": ["title", "priority", "status", "tags"], "additionalProperties": false }`),}| Provider | JSON Mode | JSON Schema Mode |
|---|---|---|
| OpenAI | ✓ | ✓ |
| Anthropic | ✓ | - |
| Gemini | ✓ | ✓ |
| xAI | ✓ | - |
| Ollama | ✓ | - |
Design schemas for specific extraction tasks rather than general-purpose structures.
Clear field names help the model understand what to extract.
Include descriptions for complex or ambiguous fields.
Even with schema enforcement, validate business logic after parsing.
Tools Guide
Combine structured output with tool calling. Tools →
Streaming Guide
Stream structured responses. Streaming →
Examples
See structured output in action. Examples →
API Reference
Full API documentation. API →