Skip to content
synthreo.ai

SDKs and Libraries

SDK and client library overview for the Builder API — links to official and community-supported libraries for integrating Synthreo AI agents into your applications.

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.

Installation:

Terminal window
npm install @synthreo/sdk
yarn add @synthreo/sdk
```text
**Quick Start:**
```javascript
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());
```text
**Advanced Features:**
```javascript
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
});
```text
### Python SDK
**Installation:**
```bash
pip install synthreo-sdk
```text
**Quick Start:**
```python
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'
)
response = client.execute_diagram(12345, "Hello AI!")
print(response.get_ai_response())
job_result = client.execute_as_job(12345, "Process this data")
print(job_result.get_output())
```text
**Advanced Features:**
```python
from synthreo import SynthreoClient, SynthreoConfig
from synthreo.webhooks import WebhookHandler
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
)
result = client.execute_diagram(12345, {
'message': 'Follow up question',
'context': {
'conversation_id': 'conv-123',
'user_id': 'user-456',
'session_data': {'preference': 'detailed'}
}
})
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_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}"))
```text
### Java SDK
**Installation (Maven):**
```xml
<dependency>
<groupId>com.synthreo</groupId>
<artifactId>synthreo-sdk</artifactId>
<version>1.0.0</version>
</dependency>
```text
**Installation (Gradle):**
```gradle
implementation 'com.synthreo:synthreo-sdk:1.0.0'
```text
**Quick Start:**
```java
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());
```text
**Advanced Features:**
```java
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()
);
```text
### C# SDK
**Installation (NuGet):**
```bash
dotnet add package Synthreo.SDK
```text
**Quick Start:**
```csharp
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());
```text
**Advanced Features:**
```csharp
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}")
});
```text
## SDK Features
### Automatic Token Management
All SDKs handle JWT token lifecycle automatically:
```javascript
// 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
```text
### Intelligent Polling vs Webhooks
SDKs automatically choose the best approach:
```python
client = SynthreoClient(credentials, config={
'webhooks': {
'enabled': True,
'fallback_to_polling': True,
'timeout': 300 # 5 minutes webhook timeout
}
})
job_result = client.execute_as_job(12345, "Long running task")
```text
### Built-in Error Handling
SDKs implement comprehensive error handling:
```java
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());
}
```text
### Response Parsing
SDKs automatically parse complex responses:
```csharp
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();
```text
## Webhook Integration
### Express.js Integration
```javascript
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);
```text
### Django Integration
```python
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)
@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'])
```text
### Spring Boot Integration
```java
@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());
}
}
```text
## Advanced Usage Patterns
### Conversation Management
```javascript
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);
```text
### Batch Processing with Progress
```python
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
results = asyncio.run(process_large_dataset())
```text
### Custom Training Workflows
```java
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());
}
```text
## SDK Configuration
### Environment-Specific Configurations
```javascript
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
);
```text
### Custom HTTP Configuration
```python
import httpx
from synthreo import SynthreoClient
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
)
```text
## Testing and Debugging
### Mock Client for Testing
```javascript
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");
});
});
```text
### Debug Mode
```python
from synthreo import SynthreoClient
import 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
}
}
)
result = client.execute_diagram(12345, "Test message")
```text
## Performance Optimization
### Connection Pooling
```java
// 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();
```text
### Caching Strategies
```csharp
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)
}
});
```text
## Migration from Raw API
### Gradual Migration Helper
```javascript
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);
}
}
```text
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.