Advanced TopicsΒΆ
π οΈ Custom HandlersΒΆ
To extend functionality, you can add new webhook routes or build custom logic for specific event types.
How to Add a New Handler:
- Create a new handler function in
internal/handlers/webhook.go
. - Register the route in your main server.
Go Code: New Handler Example
// internal/handlers/webhook.go
func CustomWebhookHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Custom webhook received!")
var payload map[string]interface{}
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
http.Error(w, "Invalid payload", http.StatusBadRequest)
return
}
// Custom logic here
w.WriteHeader(http.StatusOK)
}
Register the Route:
ποΈ Scaling Multiple ClientsΒΆ
For large or multi-tenant systems, it's useful to deploy multiple Clients with different configurations.
Why?
- Load balancing across services.
- Isolating traffic for different apps.
- Geo-distribution.
Diagram: Multi-Tenant Setup
graph TD
SourceA[Service A Webhooks] --> Client1[Client Instance A]
SourceB[Service B Webhooks] --> Client2[Client Instance B]
SourceC[Service C Webhooks] --> Client3[Client Instance C]
Client1 --> MFO[MFO Server]
Client2 --> MFO
Client3 --> MFO
Configuration Strategy:
- Each client uses a separate YAML config.
- Consider different ports or containers for isolation.
π Security ConsiderationsΒΆ
Metaphor: Locks & Keys β Every webhook should come with a key to prove its authenticity.
Example: HMAC Validation
- The sender includes a signature header (e.g.,
X-Signature
). - The Client validates the signature before processing.
Go Code: Secure Webhook
func SecureWebhookHandler(w http.ResponseWriter, r *http.Request) {
secret := []byte("your_shared_secret")
sig := r.Header.Get("X-Signature")
body, _ := io.ReadAll(r.Body)
mac := hmac.New(sha256.New, secret)
mac.Write(body)
expectedSig := hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(sig), []byte(expectedSig)) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Proceed with valid request
w.WriteHeader(http.StatusAccepted)
}
Tip: Always use HTTPS and rotate secrets regularly.
π Integration TipsΒΆ
The MFO Client is designed for seamless integration with the MFO Server API. This involves forwarding events received by the client and potentially querying the server for status or other information. All interactions with the MFO Server should be performed using the structured API client components (BaseClient
and specialized clients like EventClient
, ChatClient
, ResourceClient
, etc.) described in the Core Concepts.
Mermaid Diagram: API Flow using Structured Client
This diagram illustrates a typical flow where the client forwards an event and then might check a job status, all using its internal API client components which handle authentication and communication.
sequenceDiagram
participant WebhookListener as MFO Client Webhook Listener
participant AppLogic as Client Application Logic
participant EventClient as MFO EventClient (within AppLogic)
participant JobClient as MFO JobClient (within AppLogic)
participant MFOServer as MFO Server API
WebhookListener->>+AppLogic: Raw Event Received
AppLogic->>AppLogic: Parse & Validate Event
AppLogic->>+EventClient: ForwardEvent(parsedEvent)
EventClient->>+MFOServer: POST /api/events (Authenticated, with retries)
MFOServer-->>-EventClient: API Response (e.g., EventID, Ack)
EventClient-->>-AppLogic: Forwarding Result
AppLogic->>+JobClient: GetJobStatus(jobIDFromEvent)
JobClient->>+MFOServer: GET /api/jobs/{jobID} (Authenticated)
MFOServer-->>-JobClient: Job Status Details
JobClient-->>-AppLogic: Job Status Result
Go Code: Forwarding Event using MFO EventClient
This example demonstrates forwarding an event using an initialized EventClient
. This approach leverages the BaseClient
for actual HTTP communication, including authentication, configured timeouts, and potentially retry logic.
// Assume 'eventClient' is an instance of api.EventClientInterface,
// initialized as shown in Core Concepts or Quick Start.
// Assume 'receivedEvent' is of type models.Event or a compatible structure.
func forwardEventToMFO(ctx context.Context, eventClient api.EventClientInterface, eventData models.Event) (*models.EventResponse, error) {
log.Printf("Forwarding event type '%s' to MFO server...", eventData.Type)
// The EventClient's SendEvent method encapsulates:
// 1. Constructing the correct API request.
// 2. Adding authentication headers (via the underlying BaseClient and AuthProvider).
// 3. Making the HTTP call.
// 4. Parsing the response or API error.
// 5. The underlying BaseClient might also be configured with retry and circuit breaker logic.
response, err := eventClient.SendEvent(ctx, eventData) // eventData should match expected input
if err != nil {
log.Printf("Failed to forward event to MFO server: %v", err)
// Handle specific errors, e.g., APIError, network errors, etc.
// This is where you might trigger alerts or more sophisticated error handling.
return nil, err
}
log.Printf("Event successfully forwarded. MFO Response ID (if any): %s", response.ID) // Assuming response has an ID
return response, nil
}
// Example usage:
// ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
// defer cancel()
// _, err := forwardEventToMFO(ctx, myInitializedEventClient, anEvent)
// if err != nil { /* ... handle final error ... */ }
Best Practices for Robust Integration:
- Structured API Client: Always use the provided MFO API client components (
BaseClient
,EventClient
,ChatClient
, etc.) for all interactions with the MFO server. These clients are designed to handle authentication, request/response serialization, and base-level error interpretation. - Configuration: Externalize client configuration (base URL, timeouts, API keys/credentials) as shown in the "Client and Webhook Configuration" section of
mfo_client_4_usage_examples.md
. - Error Handling and Retries: Implement robust error handling around API calls. The MFO client should be configured with a
RetryPolicy
and potentially aCircuitBreaker
as detailed in Section 2.7 (Error Handling and Retry Logic) and Section 6.1 (Error Handling) of the main MFO Orchestrator documentation. This includes strategies like exponential backoff for transient network issues or server-side errors (e.g., 5xx status codes). - Context Propagation: Use
context.Context
for all API calls to manage deadlines, cancellations, and request-scoped values. - Asynchronous Operations: For operations like event forwarding, consider performing them asynchronously from the initial webhook reception to ensure quick responses to the event sender.
- Logging and Monitoring: Implement comprehensive logging for API interactions, including request details (without sensitive data), MFO server responses, and any errors encountered. Monitor API call latency and error rates.
π οΈ Debugging ToolsΒΆ
The check_path_consistency.go
tool is designed to validate and ensure consistency between taskflow definitions and the available tasks.
Use Cases:
- Confirm all task IDs are unique.
- Verify that all dependencies are resolvable.
- Check for orphan tasks.
Go Code: Checker Excerpt
// internal/taskflow/check_path_consistency.go
for _, task := range taskflow.Tasks {
for _, dep := range task.Dependencies {
if !taskflow.HasTask(dep) {
log.Printf("Warning: Task %s has unresolved dependency %s", task.ID, dep)
}
}
}
Run Example:
These advanced topics equip you with the tools to customize, scale, secure, and debug your Client MindFlight AI component confidently.