Skip to content

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:

  1. Create a new handler function in internal/handlers/webhook.go.
  2. 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:

http.HandleFunc("/custom-webhook", handlers.CustomWebhookHandler)

πŸ—οΈ 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

  1. The sender includes a signature header (e.g., X-Signature).
  2. 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 a CircuitBreaker 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:

go run internal/taskflow/check_path_consistency.go --input myflow.yaml

These advanced topics equip you with the tools to customize, scale, secure, and debug your Client MindFlight AI component confidently.