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.
Official SDKs
Section titled “Official SDKs”Node.js SDK
Section titled “Node.js SDK”Installation:
npm install @synthreo/sdk
yarn add @synthreo/sdk```text**Quick Start:**
```javascriptconst { 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 executionconst response = await client.executeDiagram(12345, "Hello AI!");console.log(response.getAIResponse());
// Async job with automatic pollingconst jobResult = await client.executeAsJob(12345, "Process this data");console.log(jobResult.getOutput());```text**Advanced Features:**
```javascriptconst 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 contextconst result = await client.executeDiagram(12345, { message: "Follow up question", context: { conversationId: "conv-123", userId: "user-456", previousIntent: "product_inquiry" }});
// Training workflowconst trainingResult = await client.triggerTraining(8139, { nodeId: "training-node-uuid", repositoryNodeId: 59, options: { notifyOnComplete: true, webhook: true }});
// Batch processingconst 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:**
```bashpip install synthreo-sdk```text**Quick Start:**
```pythonfrom synthreo import SynthreoClientimport 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:**
```pythonfrom synthreo import SynthreoClient, SynthreoConfigfrom 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):**
```gradleimplementation 'com.synthreo:synthreo-sdk:1.0.0'```text**Quick Start:**
```javaimport 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 executionExecutionResult response = client.executeDiagram(12345, "Hello AI!");System.out.println(response.getAIResponse());
// Async jobJobResult jobResult = client.executeAsJob(12345, "Process this data");System.out.println(jobResult.getOutput());```text**Advanced Features:**
```javaimport com.synthreo.*;import com.synthreo.config.*;import com.synthreo.webhooks.*;import java.util.concurrent.CompletableFuture;
// Advanced configurationSynthreoConfig 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 CompletableFutureCompletableFuture<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 callbackTrainingResult trainingResult = client.triggerTraining(8139, TrainingRequest.builder() .nodeId("training-node-uuid") .repositoryNodeId(59) .progressCallback(progress -> System.out.println("Training: " + progress.getState())) .build());
// Batch processingList<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):**
```bashdotnet add package Synthreo.SDK```text**Quick Start:**
```csharpusing 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 executionvar response = await client.ExecuteDiagramAsync(12345, "Hello AI!");Console.WriteLine(response.GetAIResponse());
// Async jobvar jobResult = await client.ExecuteAsJobAsync(12345, "Process this data");Console.WriteLine(jobResult.GetOutput());```text**Advanced Features:**
```csharpusing 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 executionvar 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 monitoringvar trainingResult = await client.TriggerTrainingAsync(8139, new TrainingRequest{ NodeId = "training-node-uuid", RepositoryNodeId = 59, ProgressCallback = progress => Console.WriteLine($"Training: {progress.State}")});
// Batch processingvar 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 expirationconst client = new SynthreoClient(credentials);
// No manual token management neededconst 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:
```pythonclient = 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:
```javatry { 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:
```csharpvar result = await client.ExecuteDiagramAsync(12345, "Analyze this data");
// Automatic parsing of outputData JSONstring aiResponse = result.GetAIResponse();var structuredData = result.GetStructuredOutput<MyDataModel>();
// Error information parsed automaticallyif (result.HasErrors){ foreach (var error in result.GetErrors()) { Console.WriteLine($"Error in {error.NodeName}: {error.Message}"); }}
// Metadata and debug informationvar executionMetadata = result.GetMetadata();var debugInfo = result.GetDebugInfo();```text## Webhook Integration
### Express.js Integration
```javascriptconst 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 processingapp.use('/webhooks/synthreo', webhookHandler.middleware());
// Custom event handlerswebhookHandler.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
```pythonfrom django.http import HttpResponsefrom django.views.decorators.csrf import csrf_exemptfrom synthreo import SynthreoClient, WebhookHandler
client = SynthreoClient(credentials)webhook_handler = WebhookHandler( secret=os.getenv('WEBHOOK_SECRET'), client=client)
@csrf_exemptdef 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"); } }}
@Componentpublic 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
```javascriptconst { ConversationManager } = require('@synthreo/sdk');
const conversationManager = new ConversationManager({ client: client, defaultTTL: 3600000, // 1 hour maxMessages: 10});
// Start new conversationconst conversationId = conversationManager.startConversation('user-123');
// Send messages with automatic contextconst 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 historyconst history = conversationManager.getHistory(conversationId);```text### Batch Processing with Progress
```pythonfrom synthreo import BatchProcessorimport 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
```javaimport 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 pipelineTrainingResult 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
```javascriptconst 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
```pythonimport httpxfrom 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
```javascriptconst { 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
```pythonfrom synthreo import SynthreoClientimport 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 applicationsOkHttpClient 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
```csharpvar 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
```javascriptconst { 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 workingasync 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); }}```textBy 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.