Defining what settings agents can configure when using your graph.
Overview
Configuration schema defines agent settings:
- What agents can configure - Prompts, models, tools, etc.
- UI generation - How settings appear in console
- Validation - Allowed values and constraints
- Defaults - Starting values
Location: src/versions/{version}/config-schema.json
Each version can have different configuration options.
Basic Schema
Minimal Example
json{ "version": "1.0.0", "schema": { "type": "object", "properties": { "systemPrompt": { "type": "string", "title": "System Prompt", "default": "You are a helpful assistant." } } } }
This creates one text field in the console UI where agents can set their system prompt.
Schema Structure
json{ "version": "1.0.0", // Must match version folder "schema": { // JSON Schema v7 "type": "object", "properties": { // Available settings "fieldName": { "type": "...", "title": "...", // UI label "description": "...", // Help text "default": ... // Default value } }, "required": ["fieldName"] // Required fields } }
Field Types
String
Text input field.
json{ "userName": { "type": "string", "title": "User Name", "description": "Name shown in conversations", "default": "Assistant", "minLength": 1, "maxLength": 50 } }
Options:
minLength- Minimum charactersmaxLength- Maximum characterspattern- Regex validation (e.g.,"^[a-zA-Z]+$")enum- Allowed values (see Enums)
Number
Numeric input (integers or decimals).
json{ "temperature": { "type": "number", "title": "Temperature", "description": "Controls randomness (0 = focused, 1 = creative)", "default": 0.7, "minimum": 0, "maximum": 2, "multipleOf": 0.1 } }
Options:
minimum- Minimum valuemaximum- Maximum valueexclusiveMinimum- Value must be greater than (not equal)exclusiveMaximum- Value must be less than (not equal)multipleOf- Value must be multiple of (e.g., 0.1 for one decimal)
Integer
Whole numbers only.
json{ "maxRetries": { "type": "integer", "title": "Max Retries", "default": 3, "minimum": 1, "maximum": 10 } }
Same options as number, but rejects decimals.
Boolean
Checkbox for true/false.
json{ "enableLogging": { "type": "boolean", "title": "Enable Logging", "description": "Log all conversations for debugging", "default": true } }
Object
Nested configuration group.
json{ "modelSettings": { "type": "object", "title": "Model Settings", "description": "Configuration for AI model", "properties": { "modelId": { "type": "string", "title": "Model", "enum": ["gpt-4", "gpt-3.5-turbo", "claude-3-opus"] }, "temperature": { "type": "number", "title": "Temperature", "default": 0.7 } }, "required": ["modelId"] } }
Objects create collapsible sections in UI.
Array
List of values.
json{ "keywords": { "type": "array", "title": "Keywords", "description": "Keywords to watch for", "items": { "type": "string" }, "minItems": 1, "maxItems": 10, "uniqueItems": true } }
Options:
items- Schema for each array itemminItems- Minimum array lengthmaxItems- Maximum array lengthuniqueItems- Prevent duplicates
Array of objects:
json{ "escalationRules": { "type": "array", "title": "Escalation Rules", "items": { "type": "object", "properties": { "keyword": { "type": "string" }, "action": { "type": "string", "enum": ["email", "slack"] } } } } }
modelSelector
UI for choosing AI model.
json{ "modelId": { "type": "modelSelector", "title": "AI Model", "params": { "modelType": "chat" }, "default": "gpt-4o" } }
params.modelType: "chat", "rerank", "embedding"
Returns model ID string: "gpt-4o", "claude-4-5-sonnet"
toolSelector
UI for selecting tools from catalog.
json{ "allowedTools": { "type": "toolSelector", "title": "Available Tools", "params": { "isMulti": true } } }
params.isMulti: Allow multiple selection (default: true)
Returns array of tool IDs: ["web-search", "calculator"]
kbSelector
UI for selecting knowledge bases.
json{ "knowledgeBases": { "type": "kbSelector", "title": "Knowledge Bases", "params": { "isMulti": true } } }
params.isMulti: Allow multiple selection (default: true)
Returns array of KB IDs: ["docs-kb", "support-kb"]
Format Hints
Format hints control UI rendering without changing validation.
textarea
Multi-line text input.
json{ "systemPrompt": { "type": "string", "format": "textarea", "title": "System Prompt", "default": "You are a helpful assistant." } }
Use for long text like prompts, instructions, templates.
password
Hidden input field.
json{ "apiKey": { "type": "string", "format": "password", "title": "API Key", "description": "Your secret API key" } }
Value is masked in UI and logs.
Email validation and appropriate keyboard on mobile.
json{ "contactEmail": { "type": "string", "format": "email", "title": "Contact Email" } }
uri
URL validation.
json{ "webhookUrl": { "type": "string", "format": "uri", "title": "Webhook URL", "description": "URL to send notifications" } }
date / time
Date or time picker.
json{ "startDate": { "type": "string", "format": "date", "title": "Start Date" }, "startTime": { "type": "string", "format": "time", "title": "Start Time" } }
Validation
Required Fields
Mark fields as required.
json{ "schema": { "type": "object", "properties": { "systemPrompt": { "type": "string" }, "modelId": { "type": "string" } }, "required": ["systemPrompt", "modelId"] } }
Console UI shows error if required fields are empty.
Enums
Restrict to specific values.
json{ "logLevel": { "type": "string", "title": "Log Level", "enum": ["debug", "info", "warn", "error"], "default": "info" } }
Renders as dropdown in UI.
With labels:
json{ "logLevel": { "type": "string", "title": "Log Level", "enum": ["debug", "info", "warn", "error"], "enumLabels": ["Debug (verbose)", "Info", "Warning", "Error only"], "default": "info" } }
Pattern (Regex)
Validate string format.
json{ "agentId": { "type": "string", "title": "Agent ID", "pattern": "^[a-z0-9-]+$", "description": "Lowercase letters, numbers, and hyphens only" } }
Shows error message if pattern doesn't match.
Min/Max
Number and string length constraints.
json{ "temperature": { "type": "number", "minimum": 0, "maximum": 2 }, "userName": { "type": "string", "minLength": 3, "maxLength": 50 } }
Using Configuration
Configuration is passed to your graph builder function at runtime.
TypeScript
typescript// src/versions/v1.0.0/builder.ts import { GraphConfig } from '@flutch/sdk'; export function buildGraph(config: GraphConfig) { const { systemPrompt, modelSettings, availableTools, enableLogging } = config; // Use config to build graph const llm = new ChatOpenAI({ model: modelSettings.modelId, temperature: modelSettings.temperature, maxTokens: modelSettings.maxTokens, }); if (enableLogging) { flutch.logger.info('Graph initialized', { config }); } // Build and return graph using config return graph; }
Python
python# src/versions/v1.0.0/builder.py def build_graph(config: dict): system_prompt = config["systemPrompt"] model_settings = config["modelSettings"] tools = config.get("availableTools", []) enable_logging = config.get("enableLogging", False) # Use config to build graph llm = ChatOpenAI( model=model_settings["modelId"], temperature=model_settings["temperature"], max_tokens=model_settings["maxTokens"], ) if enable_logging: flutch.logger.info("Graph initialized", extra={"config": config}) # Build and return graph using config return graph
SDK Helper
typescriptimport { flutch } from '@flutch/sdk'; export function buildGraph() { // Get config from SDK const config = flutch.config.get(); const systemPrompt = config.systemPrompt; const temperature = config.modelSettings.temperature; // Use config... }
Complete Examples
Customer Support Bot
json{ "version": "1.0.0", "schema": { "type": "object", "properties": { "systemPrompt": { "type": "promptTemplate", "title": "System Prompt", "default": "You are a helpful customer support agent for {{companyName}}.", "params": { "variables": ["companyName", "agentName"] } }, "model": { "type": "modelSelector", "title": "AI Model", "params": { "providers": ["openai", "anthropic"], "showPricing": true } }, "temperature": { "type": "number", "title": "Temperature", "default": 0.7, "minimum": 0, "maximum": 1, "ui:widget": "slider" }, "availableTools": { "type": "toolSelector", "title": "Tools", "params": { "isMulti": true, "categories": ["knowledge-base", "crm"] } }, "escalationSettings": { "type": "object", "title": "Escalation", "properties": { "enableEscalation": { "type": "boolean", "title": "Enable Escalation to Humans", "default": true }, "escalationKeywords": { "type": "array", "title": "Escalation Keywords", "items": { "type": "string" }, "default": ["refund", "manager", "cancel"], "visibleWhen": { "field": "enableEscalation", "equals": true } }, "notificationMethod": { "type": "string", "title": "Notification Method", "enum": ["email", "slack"], "default": "email", "visibleWhen": { "field": "enableEscalation", "equals": true } } } } }, "required": ["systemPrompt", "model"] } }
RAG Research Assistant
json{ "version": "1.0.0", "schema": { "type": "object", "properties": { "systemPrompt": { "type": "string", "format": "textarea", "title": "System Prompt", "default": "You are a research assistant that helps users find information." }, "vectorStore": { "type": "object", "title": "Vector Store", "properties": { "provider": { "type": "string", "title": "Provider", "enum": ["pinecone", "weaviate", "qdrant"], "default": "pinecone" }, "indexName": { "type": "string", "title": "Index Name" }, "topK": { "type": "integer", "title": "Top K Results", "default": 5, "minimum": 1, "maximum": 20 } }, "required": ["provider", "indexName"] }, "rerankSettings": { "type": "object", "title": "Reranking", "properties": { "enableRerank": { "type": "boolean", "title": "Enable Reranking", "default": false }, "rerankModel": { "type": "string", "title": "Rerank Model", "enum": ["cohere-rerank-v3", "cross-encoder"], "visibleWhen": { "field": "enableRerank", "equals": true } }, "topN": { "type": "integer", "title": "Top N After Rerank", "default": 3, "minimum": 1, "maximum": 10, "visibleWhen": { "field": "enableRerank", "equals": true } } } }, "citationStyle": { "type": "string", "title": "Citation Style", "enum": ["inline", "footnotes", "none"], "enumLabels": ["Inline [1]", "Footnotes ¹", "No Citations"], "default": "inline" } }, "required": ["systemPrompt", "vectorStore"] } }
Multi-Agent Workflow (Node-Based)
Real-world example from a production support graph with routing and specialized agents.
json{ "version": "1.0.0", "schema": { "type": "object", "properties": { "conversationRouter": { "type": "object", "title": "Conversation Router", "description": "Routes queries to the right agent", "properties": { "model": { "type": "modelSelector", "title": "Model", "modelType": "chat", "default": "gpt-4o-mini" }, "temperature": { "type": "number", "title": "Temperature", "default": 0.2, "minimum": 0, "maximum": 2 }, "systemPrompt": { "type": "string", "title": "System Prompt", "format": "textarea", "default": "You are an intelligent query router..." } } }, "authoritativeAgent": { "type": "object", "title": "Authoritative Agent", "description": "High-precision KB answers with CoRAG", "properties": { "model": { "type": "modelSelector", "title": "Model", "modelType": "chat", "default": "gpt-4o" }, "temperature": { "type": "number", "default": 0.3 }, "coragRetrieval": { "type": "object", "title": "CoRAG Retrieval", "properties": { "maxIterations": { "type": "number", "default": 3, "minimum": 1, "maximum": 10 }, "topK": { "type": "number", "default": 8, "minimum": 3, "maximum": 20 } } }, "knowledgeReranker": { "type": "object", "title": "Knowledge Reranker", "properties": { "model": { "type": "modelSelector", "title": "Rerank Model", "modelType": "rerank", "default": "cohere-rerank-v3" }, "topK": { "type": "number", "default": 8 } } } } }, "researchAgent": { "type": "object", "title": "Research Agent", "description": "Deep analysis with query decomposition", "properties": { "model": { "type": "modelSelector", "modelType": "chat", "default": "gpt-4o" }, "temperature": { "type": "number", "default": 0.7 }, "queryDecomposer": { "type": "object", "title": "Query Decomposer", "properties": { "maxSubQueries": { "type": "number", "default": 5 } } } } } } } }
Key features:
- Each major node has its own configuration object
- Nested settings (e.g.,
coragRetrievalinsideauthoritativeAgent) - Specialized selectors (
modelSelectorwithmodelType: "rerank") - Clear descriptions for each node's purpose
- UI renders as collapsible sections per node
Simple ReAct Graph
Example from production ReAct implementation.
json{ "title": "ReAct Graph v1.0.0", "type": "object", "properties": { "stepBudget": { "type": "integer", "minimum": 1, "maximum": 15, "default": 6, "description": "Maximum number of ReAct cycles" }, "allowedTools": { "type": "toolSelector", "title": "Available Tools", "params": { "isMulti": true, "showDescriptions": true } }, "reactNode": { "type": "object", "title": "ReAct Node Configuration", "properties": { "modelId": { "type": "modelSelector", "modelType": "chat", "default": "gpt-4o" }, "temperature": { "type": "number", "default": 0.7, "minimum": 0, "maximum": 2 }, "systemPrompt": { "type": "string", "format": "textarea", "default": "You are a reasoning AI assistant..." } } }, "answerNode": { "type": "object", "title": "Answer Node Configuration", "properties": { "modelId": { "type": "modelSelector", "modelType": "chat", "default": "claude-3-5-sonnet" }, "temperature": { "type": "number", "default": 0.6 } } } }, "required": ["allowedTools"] }
Note: Global settings like stepBudget and allowedTools at top level, node-specific settings grouped by node.
Best Practices
1. Provide Good Defaults
Every field should have a sensible default value.
json// ✅ Good { "temperature": { "type": "number", "default": 0.7, "description": "Recommended: 0.7 for balanced responses" } } // ❌ Bad { "temperature": { "type": "number", "description": "Set temperature" } }
2. Use Clear Descriptions
Help users understand what each field does.
json// ✅ Good { "maxTokens": { "type": "integer", "title": "Max Tokens", "description": "Maximum length of AI responses. Higher = longer answers but higher cost.", "helpText": "GPT-4: ~750 words = 1000 tokens. Recommended: 2000 for conversations." } } // ❌ Bad { "maxTokens": { "type": "integer", "title": "Tokens" } }
3. Group Related Settings by Node
Recommended: Organize configuration by graph nodes for better UI and maintainability.
json// ✅ Good - organized by nodes { "reactNode": { "type": "object", "title": "ReAct Node Configuration", "description": "Settings for the reasoning and tool selection node", "properties": { "modelId": { "type": "modelSelector", "default": "gpt-4o" }, "temperature": { "type": "number", "default": 0.7 }, "systemPrompt": { "type": "string", "format": "textarea" } } }, "answerNode": { "type": "object", "title": "Answer Node Configuration", "description": "Settings for the final answer generation node", "properties": { "modelId": { "type": "modelSelector", "default": "claude-3-5-sonnet" }, "temperature": { "type": "number", "default": 0.6 }, "systemPrompt": { "type": "string", "format": "textarea" } } } } // ❌ Bad - flat structure without grouping { "reactModel": {...}, "reactTemperature": {...}, "answerModel": {...}, "answerTemperature": {...} }
Benefits:
- UI renders each node as collapsible section
- Easy to understand which settings affect which part of the graph
- Easier to maintain and update
- Matches code structure (one config per node)
4. Validate Appropriately
Use validation to prevent errors, not to frustrate users.
json// ✅ Good - reasonable constraints { "userName": { "type": "string", "minLength": 1, "maxLength": 100 } } // ❌ Too strict { "userName": { "type": "string", "pattern": "^[a-z]{3,10}$", "minLength": 3, "maxLength": 10 } }
5. Use Conditional Fields Wisely
Hide complexity until needed.
json// ✅ Good { "enableAdvanced": { "type": "boolean", "title": "Enable Advanced Settings", "default": false }, "advancedSettings": { "type": "object", "visibleWhen": { "field": "enableAdvanced", "equals": true }, "properties": { "timeout": {...}, "retryStrategy": {...} } } }
6. Keep It Simple
Start with essential settings, add more as needed.
json// ✅ Good for v1.0.0 { "systemPrompt": {...}, "model": {...}, "temperature": {...} } // Can expand in v2.0.0 with more advanced options
7. Use Enums for Fixed Choices
Prevent typos and show available options.
json// ✅ Good { "logLevel": { "type": "string", "enum": ["debug", "info", "warn", "error"] } } // ❌ Bad - allows any string { "logLevel": { "type": "string" } }
Troubleshooting
Schema Validation Failed
Error: Invalid schema: properties.temperature.type must be 'number'
Fix: Check JSON Schema syntax. Common issues:
- Typo in
typevalue - Missing required fields
- Invalid constraint combination
UI Not Rendering Field
Field defined but doesn't appear in console UI.
Check:
- Is field inside
propertiesobject? - Is parent object visible (check
visibleWhenconditions)? - Is version number in schema correct?
Default Value Not Applied
json{ "temperature": { "type": "number", "default": "0.7" // ❌ String instead of number } }
Fix: Ensure default value type matches field type:
json{ "temperature": { "type": "number", "default": 0.7 // ✅ Correct } }
Conditional Field Not Showing
json{ "cacheTTL": { "visibleWhen": { "field": "enableCache", // ❌ Wrong field path "equals": true } } }
Fix: Use correct field path:
json{ "cacheTTL": { "visibleWhen": { "field": "cacheSettings.enableCache", // ✅ Correct nested path "equals": true } } }
Test Schema Validation
bash# Validate schema without deploying flutch validate # Test with sample config flutch config:test src/versions/v1.0.0/config-schema.json