Skip to main content

SDKs and Libraries

Synthreo provides official SDKs and libraries to simplify integration with the Builder API. These SDKs implement all the best practices covered in our documentation, including authentication management, error handling, rate limiting, and webhook processing.

Official SDKs

Node.js SDK

Installation:

npm install @synthreo/sdk
# or
yarn add @synthreo/sdk

Quick Start:

const { SynthreoClient } = require('@synthreo/sdk');

const client = new SynthreoClient({
email: process.env.SYNTHREO_API_EMAIL,
password: process.env.SYNTHREO_API_PASSWORD,
userId: parseInt(process.env.SYNTHREO_USER_ID),
environment: 'production' // or 'development'
});

// Simple execution
const response = await client.executeDiagram(12345, "Hello AI!");
console.log(response.getAIResponse());

// Async job with automatic polling
const jobResult = await client.executeAsJob(12345, "Process this data");
console.log(jobResult.getOutput());

Advanced Features:

const client = new SynthreoClient({
email: process.env.SYNTHREO_API_EMAIL,
password: process.env.SYNTHREO_API_PASSWORD,
userId: parseInt(process.env.SYNTHREO_USER_ID),

// Advanced configuration
options: {
// Rate limiting
rateLimiting: {
requestsPerMinute: 60,
enableQueue: true,
maxConcurrent: 5
},

// Polling configuration
polling: {
jobInterval: 30000, // 30 seconds
trainingInterval: 60000, // 60 seconds
timeout: 3600000 // 1 hour
},

// Retry configuration
retry: {
maxAttempts: 3,
baseDelay: 1000,
exponentialBackoff: true
},

// Caching
caching: {
enabled: true,
tokenTTL: 86400000, // 24 hours
responseTTL: 300000 // 5 minutes
},

// Webhooks
webhooks: {
enabled: true,
secret: process.env.WEBHOOK_SECRET,
endpoint: '/webhooks/synthreo',
fallbackToPolling: true
}
}
});

// Execute with conversation context
const result = await client.executeDiagram(12345, {
message: "Follow up question",
context: {
conversationId: "conv-123",
userId: "user-456",
previousIntent: "product_inquiry"
}
});

// Training workflow
const trainingResult = await client.triggerTraining(8139, {
nodeId: "training-node-uuid",
repositoryNodeId: 59,
options: {
notifyOnComplete: true,
webhook: true
}
});

// Batch processing
const batchResults = await client.executeBatch([
{ diagramId: 12345, message: "Query 1" },
{ diagramId: 12345, message: "Query 2" },
{ diagramId: 12345, message: "Query 3" }
], {
concurrency: 3,
retryFailed: true
});

Python SDK

Installation:

pip install synthreo-sdk

Quick Start:

from synthreo import SynthreoClient
import os

client = SynthreoClient(
email=os.getenv('SYNTHREO_API_EMAIL'),
password=os.getenv('SYNTHREO_API_PASSWORD'),
user_id=int(os.getenv('SYNTHREO_USER_ID')),
environment='production'
)

# Simple execution
response = client.execute_diagram(12345, "Hello AI!")
print(response.get_ai_response())

# Async job with automatic polling
job_result = client.execute_as_job(12345, "Process this data")
print(job_result.get_output())

Advanced Features:

from synthreo import SynthreoClient, SynthreoConfig
from synthreo.webhooks import WebhookHandler

# Advanced configuration
config = SynthreoConfig(
rate_limiting={
'requests_per_minute': 60,
'enable_queue': True,
'max_concurrent': 5
},
polling={
'job_interval': 30, # 30 seconds
'training_interval': 60, # 60 seconds
'timeout': 3600 # 1 hour
},
retry={
'max_attempts': 3,
'base_delay': 1.0,
'exponential_backoff': True
},
webhooks={
'enabled': True,
'secret': os.getenv('WEBHOOK_SECRET'),
'fallback_to_polling': True
}
)

client = SynthreoClient(
email=os.getenv('SYNTHREO_API_EMAIL'),
password=os.getenv('SYNTHREO_API_PASSWORD'),
user_id=int(os.getenv('SYNTHREO_USER_ID')),
config=config
)

# Context-aware execution
result = client.execute_diagram(12345, {
'message': 'Follow up question',
'context': {
'conversation_id': 'conv-123',
'user_id': 'user-456',
'session_data': {'preference': 'detailed'}
}
})

# Training with monitoring
training_result = client.trigger_training(8139, {
'node_id': 'training-node-uuid',
'repository_node_id': 59,
'monitor_progress': True,
'callback': lambda progress: print(f"Training progress: {progress['state']}")
})

# Batch processing with progress tracking
batch_results = client.execute_batch([
{'diagram_id': 12345, 'message': 'Query 1'},
{'diagram_id': 12345, 'message': 'Query 2'},
{'diagram_id': 12345, 'message': 'Query 3'}
], progress_callback=lambda done, total: print(f"Progress: {done}/{total}"))

Java SDK

Installation (Maven):

<dependency>
<groupId>com.synthreo</groupId>
<artifactId>synthreo-sdk</artifactId>
<version>1.0.0</version>
</dependency>

Installation (Gradle):

implementation 'com.synthreo:synthreo-sdk:1.0.0'

Quick Start:

import com.synthreo.SynthreoClient;
import com.synthreo.models.ExecutionResult;

SynthreoClient client = SynthreoClient.builder()
.email(System.getenv("SYNTHREO_API_EMAIL"))
.password(System.getenv("SYNTHREO_API_PASSWORD"))
.userId(Integer.parseInt(System.getenv("SYNTHREO_USER_ID")))
.environment(Environment.PRODUCTION)
.build();

// Simple execution
ExecutionResult response = client.executeDiagram(12345, "Hello AI!");
System.out.println(response.getAIResponse());

// Async job
JobResult jobResult = client.executeAsJob(12345, "Process this data");
System.out.println(jobResult.getOutput());

Advanced Features:

import com.synthreo.*;
import com.synthreo.config.*;
import com.synthreo.webhooks.*;
import java.util.concurrent.CompletableFuture;

// Advanced configuration
SynthreoConfig config = SynthreoConfig.builder()
.rateLimiting(RateLimitConfig.builder()
.requestsPerMinute(60)
.enableQueue(true)
.maxConcurrent(5)
.build())
.polling(PollingConfig.builder()
.jobInterval(Duration.ofSeconds(30))
.trainingInterval(Duration.ofSeconds(60))
.timeout(Duration.ofHours(1))
.build())
.webhooks(WebhookConfig.builder()
.enabled(true)
.secret(System.getenv("WEBHOOK_SECRET"))
.fallbackToPolling(true)
.build())
.build();

SynthreoClient client = SynthreoClient.builder()
.email(System.getenv("SYNTHREO_API_EMAIL"))
.password(System.getenv("SYNTHREO_API_PASSWORD"))
.userId(Integer.parseInt(System.getenv("SYNTHREO_USER_ID")))
.config(config)
.build();

// Async execution with CompletableFuture
CompletableFuture<ExecutionResult> future = client.executeDiagramAsync(12345,
ExecutionRequest.builder()
.message("Hello AI!")
.context(Map.of(
"conversationId", "conv-123",
"userId", "user-456"
))
.build()
);

future.thenAccept(result -> {
System.out.println("AI Response: " + result.getAIResponse());
});

// Training with callback
TrainingResult trainingResult = client.triggerTraining(8139,
TrainingRequest.builder()
.nodeId("training-node-uuid")
.repositoryNodeId(59)
.progressCallback(progress ->
System.out.println("Training: " + progress.getState()))
.build()
);

// Batch processing
List<BatchRequest> requests = Arrays.asList(
BatchRequest.of(12345, "Query 1"),
BatchRequest.of(12345, "Query 2"),
BatchRequest.of(12345, "Query 3")
);

List<ExecutionResult> results = client.executeBatch(requests,
BatchOptions.builder()
.concurrency(3)
.retryFailed(true)
.progressCallback((done, total) ->
System.out.println(String.format("Progress: %d/%d", done, total)))
.build()
);

C# SDK

Installation (NuGet):

dotnet add package Synthreo.SDK

Quick Start:

using Synthreo;

var client = new SynthreoClient(new SynthreoOptions
{
Email = Environment.GetEnvironmentVariable("SYNTHREO_API_EMAIL"),
Password = Environment.GetEnvironmentVariable("SYNTHREO_API_PASSWORD"),
UserId = int.Parse(Environment.GetEnvironmentVariable("SYNTHREO_USER_ID")),
Environment = SynthreoEnvironment.Production
});

// Simple execution
var response = await client.ExecuteDiagramAsync(12345, "Hello AI!");
Console.WriteLine(response.GetAIResponse());

// Async job
var jobResult = await client.ExecuteAsJobAsync(12345, "Process this data");
Console.WriteLine(jobResult.GetOutput());

Advanced Features:

using Synthreo;
using Synthreo.Configuration;
using Synthreo.Webhooks;

var config = new SynthreoConfiguration
{
RateLimiting = new RateLimitConfiguration
{
RequestsPerMinute = 60,
EnableQueue = true,
MaxConcurrent = 5
},
Polling = new PollingConfiguration
{
JobInterval = TimeSpan.FromSeconds(30),
TrainingInterval = TimeSpan.FromSeconds(60),
Timeout = TimeSpan.FromHours(1)
},
Webhooks = new WebhookConfiguration
{
Enabled = true,
Secret = Environment.GetEnvironmentVariable("WEBHOOK_SECRET"),
FallbackToPolling = true
}
};

var client = new SynthreoClient(new SynthreoOptions
{
Email = Environment.GetEnvironmentVariable("SYNTHREO_API_EMAIL"),
Password = Environment.GetEnvironmentVariable("SYNTHREO_API_PASSWORD"),
UserId = int.Parse(Environment.GetEnvironmentVariable("SYNTHREO_USER_ID")),
Configuration = config
});

// Context-aware execution
var result = await client.ExecuteDiagramAsync(12345, new ExecutionRequest
{
Message = "Follow up question",
Context = new Dictionary<string, object>
{
["conversationId"] = "conv-123",
["userId"] = "user-456",
["preferences"] = new { language = "en", detailed = true }
}
});

// Training with progress monitoring
var trainingResult = await client.TriggerTrainingAsync(8139, new TrainingRequest
{
NodeId = "training-node-uuid",
RepositoryNodeId = 59,
ProgressCallback = progress => Console.WriteLine($"Training: {progress.State}")
});

// Batch processing
var requests = new[]
{
new BatchRequest(12345, "Query 1"),
new BatchRequest(12345, "Query 2"),
new BatchRequest(12345, "Query 3")
};

var results = await client.ExecuteBatchAsync(requests, new BatchOptions
{
Concurrency = 3,
RetryFailed = true,
ProgressCallback = (done, total) => Console.WriteLine($"Progress: {done}/{total}")
});

SDK Features

Automatic Token Management

All SDKs handle JWT token lifecycle automatically:

// Token is automatically refreshed before expiration
const client = new SynthreoClient(credentials);

// No manual token management needed
const result1 = await client.executeDiagram(12345, "Message 1");
// ... 23 hours later ...
const result2 = await client.executeDiagram(12345, "Message 2"); // Auto-refreshes token

Intelligent Polling vs Webhooks

SDKs automatically choose the best approach:

client = SynthreoClient(credentials, config={
'webhooks': {
'enabled': True,
'fallback_to_polling': True,
'timeout': 300 # 5 minutes webhook timeout
}
})

# Will use webhooks if configured, otherwise intelligent polling
job_result = client.execute_as_job(12345, "Long running task")

Built-in Error Handling

SDKs implement comprehensive error handling:

try {
ExecutionResult result = client.executeDiagram(12345, "Hello AI!");
System.out.println(result.getAIResponse());

} catch (AuthenticationException e) {
// Automatic token refresh attempted
logger.error("Authentication failed: " + e.getMessage());

} catch (RateLimitException e) {
// Automatic retry with exponential backoff
logger.warn("Rate limited, retrying: " + e.getRetryAfter());

} catch (DiagramExecutionException e) {
// Cognitive diagram internal errors
logger.error("Execution failed: " + e.getErrorData());

} catch (SynthreoException e) {
// General API errors
logger.error("API error: " + e.getMessage());
}

Response Parsing

SDKs automatically parse complex responses:

var result = await client.ExecuteDiagramAsync(12345, "Analyze this data");

// Automatic parsing of outputData JSON
string aiResponse = result.GetAIResponse();
var structuredData = result.GetStructuredOutput<MyDataModel>();

// Error information parsed automatically
if (result.HasErrors)
{
foreach (var error in result.GetErrors())
{
Console.WriteLine($"Error in {error.NodeName}: {error.Message}");
}
}

// Metadata and debug information
var executionMetadata = result.GetMetadata();
var debugInfo = result.GetDebugInfo();

Webhook Integration

Express.js Integration

const express = require('express');
const { SynthreoClient, WebhookHandler } = require('@synthreo/sdk');

const app = express();
const client = new SynthreoClient(credentials);
const webhookHandler = new WebhookHandler({
secret: process.env.WEBHOOK_SECRET,
client: client // Links webhooks to client for automatic job resolution
});

// Automatic webhook processing
app.use('/webhooks/synthreo', webhookHandler.middleware());

// Custom event handlers
webhookHandler.on('job.completed', async (data, event) => {
console.log(`Job ${data.job.id} completed`);
// Custom business logic
await notifyUser(data.job.id, 'Task completed!');
});

webhookHandler.on('training.completed', async (data, event) => {
console.log(`Training completed for agent ${data.agent.id}`);
// Enable agent for production
await enableAgentInProduction(data.agent.id);
});

app.listen(3000);

Django Integration

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from synthreo import SynthreoClient, WebhookHandler

client = SynthreoClient(credentials)
webhook_handler = WebhookHandler(
secret=os.getenv('WEBHOOK_SECRET'),
client=client
)

@csrf_exempt
def synthreo_webhook(request):
if request.method == 'POST':
# Automatic signature verification and processing
result = webhook_handler.process_request(
body=request.body,
headers=request.META
)
return HttpResponse('OK', status=200)
return HttpResponse('Method not allowed', status=405)

# Custom event handlers
@webhook_handler.on('job.completed')
def handle_job_completion(data, event):
print(f"Job {data['job']['id']} completed")
# Custom business logic
notify_user(data['job']['id'], 'Task completed!')

@webhook_handler.on('training.completed')
def handle_training_completion(data, event):
print(f"Training completed for agent {data['agent']['id']}")
# Enable agent for production
enable_agent_in_production(data['agent']['id'])

Spring Boot Integration

@RestController
@RequestMapping("/webhooks")
public class SynthreoWebhookController {

@Autowired
private SynthreoClient client;

@Autowired
private WebhookHandler webhookHandler;

@PostMapping("/synthreo")
public ResponseEntity<String> handleWebhook(
@RequestBody String payload,
@RequestHeader Map<String, String> headers) {

try {
// Automatic signature verification and processing
webhookHandler.processWebhook(payload, headers);
return ResponseEntity.ok("OK");

} catch (WebhookVerificationException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid signature");

} catch (Exception e) {
logger.error("Webhook processing error", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error");
}
}
}

@Component
public class SynthreoEventHandlers {

@EventListener
public void handleJobCompletion(JobCompletedEvent event) {
System.out.println("Job " + event.getJobId() + " completed");
// Custom business logic
notifyUser(event.getJobId(), "Task completed!");
}

@EventListener
public void handleTrainingCompletion(TrainingCompletedEvent event) {
System.out.println("Training completed for agent " + event.getAgentId());
// Enable agent for production
enableAgentInProduction(event.getAgentId());
}
}

Advanced Usage Patterns

Conversation Management

const { ConversationManager } = require('@synthreo/sdk');

const conversationManager = new ConversationManager({
client: client,
defaultTTL: 3600000, // 1 hour
maxMessages: 10
});

// Start new conversation
const conversationId = conversationManager.startConversation('user-123');

// Send messages with automatic context
const response1 = await conversationManager.sendMessage(
conversationId,
12345,
"What are your business hours?"
);

const response2 = await conversationManager.sendMessage(
conversationId,
12345,
"What about holidays?" // Context from previous messages automatically included
);

// Get conversation history
const history = conversationManager.getHistory(conversationId);

Batch Processing with Progress

from synthreo import BatchProcessor
import asyncio

batch_processor = BatchProcessor(client, max_concurrency=5)

async def process_large_dataset():
# Process 1000 items with progress tracking
tasks = [
{'diagram_id': 12345, 'message': f'Process item {i}'}
for i in range(1000)
]

results = []
async for result in batch_processor.process_batch(
tasks,
progress_callback=lambda done, total: print(f"Progress: {done}/{total}")
):
results.append(result)

# Process results as they come in
if result.is_success():
await save_result(result.get_output())
else:
await log_error(result.get_error())

return results

# Run batch processing
results = asyncio.run(process_large_dataset())

Custom Training Workflows

import com.synthreo.training.*;

TrainingWorkflow workflow = TrainingWorkflow.builder()
.client(client)
.dataPreparationStage(DataPreparationStage.builder()
.diagramId(10233) // Training data producer
.inputData(Map.of("dataSource", "https://docs.company.com"))
.pollInterval(Duration.ofSeconds(30))
.build())
.trainingStage(TrainingStage.builder()
.diagramId(8139) // RAG model
.nodeId("training-node-uuid")
.pollInterval(Duration.ofSeconds(60))
.build())
.validationStage(ValidationStage.builder()
.testQueries(Arrays.asList(
"What is our return policy?",
"How do I track my order?",
"What are your business hours?"
))
.successThreshold(0.85) // 85% accuracy required
.build())
.build();

// Execute complete training pipeline
TrainingResult result = workflow.execute();

if (result.isSuccess()) {
System.out.println("Training completed successfully!");
System.out.println("Validation score: " + result.getValidationScore());
} else {
System.out.println("Training failed: " + result.getError());
}

SDK Configuration

Environment-Specific Configurations

const developmentConfig = {
environment: 'development',
rateLimiting: {
requestsPerMinute: 30,
enableQueue: false
},
polling: {
jobInterval: 5000, // 5 seconds for faster development
trainingInterval: 15000 // 15 seconds
},
logging: {
level: 'debug',
verbose: true
}
};

const productionConfig = {
environment: 'production',
rateLimiting: {
requestsPerMinute: 60,
enableQueue: true,
maxConcurrent: 10
},
polling: {
jobInterval: 30000, // 30 seconds
trainingInterval: 60000 // 60 seconds
},
logging: {
level: 'info',
verbose: false
},
monitoring: {
enabled: true,
metricsEndpoint: '/metrics'
}
};

const client = new SynthreoClient(credentials,
process.env.NODE_ENV === 'production' ? productionConfig : developmentConfig
);

Custom HTTP Configuration

import httpx
from synthreo import SynthreoClient

# Custom HTTP client with advanced configuration
http_client = httpx.AsyncClient(
timeout=httpx.Timeout(30.0, connect=10.0),
limits=httpx.Limits(max_keepalive_connections=20, max_connections=100),
http2=True
)

client = SynthreoClient(
email=os.getenv('SYNTHREO_API_EMAIL'),
password=os.getenv('SYNTHREO_API_PASSWORD'),
user_id=int(os.getenv('SYNTHREO_USER_ID')),
http_client=http_client
)

Testing and Debugging

Mock Client for Testing

const { MockSynthreoClient } = require('@synthreo/sdk/testing');

describe('AI Agent Integration', () => {
let client;

beforeEach(() => {
client = new MockSynthreoClient();

// Configure mock responses
client.mockDiagram(12345)
.withInput("Hello AI!")
.returnsOutput("Hello! How can I help you?");

client.mockJob(12345)
.withInput("Process data")
.completesAfter(5000) // 5 seconds
.returnsOutput("Data processing completed");
});

it('should handle simple AI interactions', async () => {
const response = await client.executeDiagram(12345, "Hello AI!");
expect(response.getAIResponse()).toBe("Hello! How can I help you?");
});

it('should handle async jobs', async () => {
const jobResult = await client.executeAsJob(12345, "Process data");
expect(jobResult.getOutput()).toBe("Data processing completed");
});
});

Debug Mode

from synthreo import SynthreoClient
import logging

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)

client = SynthreoClient(
credentials,
debug=True, # Enables request/response logging
config={
'logging': {
'log_requests': True,
'log_responses': True,
'log_headers': False, # Don't log auth headers
'max_body_length': 1000 # Truncate large payloads
}
}
)

# All requests will be logged with timing information
result = client.execute_diagram(12345, "Test message")

Performance Optimization

Connection Pooling

// Configure connection pooling for high-throughput applications
OkHttpClient httpClient = new OkHttpClient.Builder()
.connectionPool(new ConnectionPool(50, 5, TimeUnit.MINUTES))
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build();

SynthreoClient client = SynthreoClient.builder()
.credentials(credentials)
.httpClient(httpClient)
.config(SynthreoConfig.builder()
.rateLimiting(RateLimitConfig.builder()
.requestsPerMinute(120) // Higher limits for enterprise
.maxConcurrent(20)
.build())
.build())
.build();

Caching Strategies

var client = new SynthreoClient(credentials, new SynthreoConfiguration
{
Caching = new CachingConfiguration
{
Enabled = true,

// Cache frequently accessed diagram info
DiagramInfoTTL = TimeSpan.FromHours(1),

// Cache authentication tokens
TokenTTL = TimeSpan.FromHours(23), // Refresh 1 hour before expiry

// Cache short-lived responses
ResponseTTL = TimeSpan.FromMinutes(5),

// Custom cache provider
CacheProvider = new RedisCacheProvider(connectionString)
}
});

Migration from Raw API

Gradual Migration Helper

const { SynthreoClient, MigrationHelper } = require('@synthreo/sdk');

const migrationHelper = new MigrationHelper({
existingHttpClient: yourExistingHttpClient, // Keep existing setup
synthreoClient: new SynthreoClient(credentials) // New SDK client
});

// Gradual migration - use SDK for new features, keep existing code working
async function executeWithMigration(diagramId, message) {
if (migrationHelper.shouldUseSdk(diagramId)) {
// Use new SDK for better features
return migrationHelper.client.executeDiagram(diagramId, message);
} else {
// Fall back to existing implementation
return migrationHelper.executeWithExistingClient(diagramId, message);
}
}

By using the official Synthreo SDKs, you get production-ready implementations of all the patterns and best practices covered in our API documentation, with automatic handling of authentication, rate limiting, error recovery, and webhook processing.