API Integration Guide
π API Integration Guide
Complete guide to using the Insight Ingenious REST API for integrating conversation workflows into your applications.
π Quick Start
Basic API Call
curl -X POST http://localhost:80/api/v1/chat \
-H "Content-Type: application/json" \
-d '{
"user_prompt": "Hello, how are you?",
"conversation_flow": "classification-agent"
}'
Response Format
{
"thread_id": "thread_123",
"message_id": "msg_456",
"agent_response": "...",
"token_count": 150,
"memory_summary": "User greeted the system"
}
π Workflow Categories
β Minimal Configuration Workflows
These work with just Azure OpenAI setup:
Classification Agent
Route input to specialized agents based on content:
curl -X POST http://localhost:80/api/v1/chat \
-H "Content-Type: application/json" \
-d '{
"user_prompt": "Analyze this customer feedback: Great product, fast delivery!",
"conversation_flow": "classification-agent"
}'
Bike Insights
Sample domain-specific workflow for business analysis:
curl -X POST http://localhost:80/api/v1/chat \
-H "Content-Type: application/json" \
-d '{
"user_prompt": "Show me bike sales trends for April 2023",
"conversation_flow": "bike-insights"
}'
π Local Knowledge Base (Stable Implementation)
Knowledge Base Agent
Search and retrieve information using local ChromaDB storage:
curl -X POST http://localhost:80/api/v1/chat \
-H "Content-Type: application/json" \
-d '{
"user_prompt": "Find health and safety information about workplace hazards",
"conversation_flow": "knowledge-base-agent"
}'
Requirements:
- None! Uses local ChromaDB automatically
- Simply add documents to
./.tmp/knowledge_base/
π Local Database (Stable Implementation)
SQL Manipulation Agent
Execute SQL queries using local SQLite database:
curl -X POST http://localhost:80/api/v1/chat \
-H "Content-Type: application/json" \
-d '{
"user_prompt": "Show me the average student performance by subject",
"conversation_flow": "sql-manipulation-agent"
}'
Requirements:
- Set
database_name: "skip"
in profiles.yml for SQLite mode - Local SQLite database automatically created
π§ Experimental Azure Integrations (May contain bugs)
Azure Search (Experimental)
- Requires Azure Cognitive Search service
- May contain bugs - use local ChromaDB instead
Azure SQL (Experimental)
- Requires Azure SQL Database
- May contain bugs - use local SQLite instead
π§ Configuration Management
Check Workflow Status
Before using a workflow, check if itβs properly configured:
# Check all workflows
curl http://localhost:80/api/v1/workflows
# Check specific workflow
curl http://localhost:80/api/v1/workflow-status/knowledge-base-agent
Example response:
{
"workflow": "knowledge-base-agent",
"configured": false,
"missing_config": [
"azure_search_services.key: Missing in profiles.yml"
],
"required_config": ["models", "chat_service", "azure_search_services"],
"external_services": ["Azure OpenAI", "Azure Cognitive Search"],
"ready": false,
"test_command": "curl -X POST http://localhost:80/api/v1/chat...",
"documentation": "See docs/workflows/README.md for setup instructions"
}
π Authentication
Basic Authentication
When authentication is enabled:
# Using basic auth
curl -X POST http://localhost:80/api/v1/chat \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n username:password | base64)" \
-d '{
"user_prompt": "Hello",
"conversation_flow": "classification-agent"
}'
Disable Authentication
For development, disable in profiles.yml
:
web_configuration:
authentication:
enable: false
π¬ Conversation Management
Thread Continuity
Maintain conversation context using thread IDs:
# First message
curl -X POST http://localhost:80/api/v1/chat \
-H "Content-Type: application/json" \
-d '{
"user_prompt": "Hello, my name is John",
"conversation_flow": "classification-agent",
"thread_id": "user-john-session-1"
}'
# Follow-up message (same thread_id)
curl -X POST http://localhost:80/api/v1/chat \
-H "Content-Type: application/json" \
-d '{
"user_prompt": "What did I just tell you my name was?",
"conversation_flow": "classification-agent",
"thread_id": "user-john-session-1"
}'
Get Conversation History
curl http://localhost:80/api/v1/conversations/user-john-session-1
π Request & Response Reference
Chat Request
{
"user_prompt": string, // Required: User's message
"conversation_flow": string, // Required: Workflow to use
"thread_id"?: string, // Optional: For conversation continuity
"topic"?: string | string[], // Optional: Additional context
"memory_record"?: boolean, // Optional: Whether to save to memory
"thread_memory"?: string, // Optional: Previous context
"event_type"?: string // Optional: Event classification
}
Chat Response
{
"thread_id": string, // Conversation thread identifier
"message_id": string, // Unique message identifier
"agent_response": string, // AI agent's response
"token_count": number, // Tokens used in generation
"max_token_count": number, // Maximum tokens allowed
"memory_summary": string, // Summary for memory storage
"content_filter_results"?: any, // Content filtering results
"tool_calls"?: any, // Any tool calls made
"tool_call_id"?: string, // Tool call identifier
"tool_call_function"?: any // Tool function details
}
π¨ Error Handling
Common Error Responses
400 Bad Request
{
"detail": "conversation_flow not set",
"workflow": null,
"available_workflows": ["classification-agent", "bike-insights", "..."]
}
404 Workflow Not Found
{
"detail": "Unknown workflow: invalid_workflow",
"available_workflows": ["classification-agent", "bike-insights", "..."]
}
406 Not Acceptable
{
"detail": "Content filtered by Azure OpenAI safety systems"
}
413 Payload Too Large
{
"detail": "Token limit exceeded. Reduce message size or conversation history."
}
500 Internal Server Error
{
"detail": "Azure Search service not configured",
"workflow": "knowledge-base-agent",
"required_config": ["azure_search_services.endpoint", "azure_search_services.key"],
"documentation": "See docs/workflows/README.md for setup instructions"
}
Error Handling Best Practices
import requests
import json
def call_ingenious_api(prompt, workflow, thread_id=None):
"""Example error handling for API calls"""
payload = {
"user_prompt": prompt,
"conversation_flow": workflow
}
if thread_id:
payload["thread_id"] = thread_id
try:
response = requests.post(
"http://localhost:80/api/v1/chat",
headers={"Content-Type": "application/json"},
json=payload,
timeout=30
)
if response.status_code == 200:
return response.json()
elif response.status_code == 400:
error = response.json()
print(f"Bad request: {error['detail']}")
if 'available_workflows' in error:
print(f"Available workflows: {error['available_workflows']}")
elif response.status_code == 406:
print("Content was filtered by safety systems")
elif response.status_code == 413:
print("Message too long, try reducing the size")
elif response.status_code == 500:
error = response.json()
print(f"Configuration error: {error['detail']}")
if 'required_config' in error:
print(f"Missing configuration: {error['required_config']}")
else:
print(f"Unexpected error: {response.status_code}")
except requests.exceptions.Timeout:
print("Request timed out")
except requests.exceptions.ConnectionError:
print("Could not connect to server")
except Exception as e:
print(f"Unexpected error: {e}")
# Usage examples
call_ingenious_api("Hello", "classification-agent")
call_ingenious_api("Search for safety info", "knowledge-base-agent")
π Integration Patterns
Webhook Integration
For real-time processing:
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def handle_webhook():
"""Process incoming webhooks with Insight Ingenious"""
data = request.json
user_message = data.get('message', '')
# Route to appropriate workflow based on content
if 'search' in user_message.lower():
workflow = 'knowledge-base-agent'
elif 'sql' in user_message.lower() or 'database' in user_message.lower():
workflow = 'sql-manipulation-agent'
else:
workflow = 'classification-agent'
# Call Insight Ingenious API
response = requests.post(
"http://localhost:80/api/v1/chat",
json={
"user_prompt": user_message,
"conversation_flow": workflow,
"thread_id": data.get('user_id', 'anonymous')
}
)
if response.status_code == 200:
result = response.json()
return jsonify({
"status": "success",
"response": result["agent_response"],
"workflow_used": workflow
})
else:
return jsonify({
"status": "error",
"message": "Processing failed"
}), 500
Batch Processing
For processing multiple requests:
import asyncio
import aiohttp
async def process_batch(messages, workflow="classification-agent"):
"""Process multiple messages in parallel"""
async def process_single(session, message, index):
payload = {
"user_prompt": message,
"conversation_flow": workflow,
"thread_id": f"batch_{index}"
}
async with session.post(
"http://localhost:80/api/v1/chat",
json=payload
) as response:
if response.status == 200:
return await response.json()
else:
return {"error": f"Status {response.status}"}
async with aiohttp.ClientSession() as session:
tasks = [
process_single(session, msg, i)
for i, msg in enumerate(messages)
]
return await asyncio.gather(*tasks)
# Usage
messages = [
"Analyze customer satisfaction",
"Search for product information",
"Generate sales report"
]
results = asyncio.run(process_batch(messages))
π― Best Practices
1. Choose the Right Workflow
- Simple classification/routing:
classification-agent
- Domain-specific analysis:
bike-insights
(or create custom) - Knowledge retrieval:
knowledge-base-agent
- Database queries:
sql-manipulation-agent
2. Handle Configuration Gracefully
Always check workflow status before using:
def ensure_workflow_ready(workflow_name):
"""Check if workflow is properly configured"""
response = requests.get(
f"http://localhost:80/api/v1/workflow-status/{workflow_name}"
)
if response.status_code == 200:
status = response.json()
if not status["ready"]:
print(f"Workflow {workflow_name} not ready:")
for missing in status["missing_config"]:
print(f" - {missing}")
return False
return True
else:
print(f"Could not check status for {workflow_name}")
return False
3. Implement Retry Logic
import time
from functools import wraps
def retry_on_failure(max_retries=3, delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_retries - 1:
raise e
print(f"Attempt {attempt + 1} failed: {e}")
time.sleep(delay * (2 ** attempt)) # Exponential backoff
return None
return wrapper
return decorator
@retry_on_failure(max_retries=3)
def call_api_with_retry(prompt, workflow):
# Your API call logic here
pass
4. Monitor Performance
import time
import logging
def monitor_api_call(prompt, workflow):
"""Monitor API performance"""
start_time = time.time()
try:
response = requests.post(
"http://localhost:80/api/v1/chat",
json={"user_prompt": prompt, "conversation_flow": workflow},
timeout=30
)
duration = time.time() - start_time
if response.status_code == 200:
result = response.json()
logging.info(f"API call successful - Duration: {duration:.2f}s, Tokens: {result.get('token_count', 0)}")
return result
else:
logging.error(f"API call failed - Status: {response.status_code}, Duration: {duration:.2f}s")
except Exception as e:
duration = time.time() - start_time
logging.error(f"API call exception - Duration: {duration:.2f}s, Error: {e}")
π Additional Resources
- Workflow Requirements - Understand configuration needs
- Configuration Guide - Detailed setup instructions
- Custom Agents - Create your own workflows
- Troubleshooting - Common issues and solutions
π Ready to integrate? Start with the minimal configuration workflows and gradually add more advanced features as your needs grow.