Skip to content

Support SageOx AgentX as hosted backend #3

@rsnodgrass

Description

@rsnodgrass

Summary

frictionax currently assumes a self-hosted frictionax-server. To support SageOx AgentX as a hosted option, several components need updates to handle different URL paths, authentication, and response formats.

Gaps

1. HTTPSource URL path is hardcoded

source.go:34 constructs:

{baseURL}/api/v1/friction/patterns?min_count={N}&limit={N}

SageOx AgentX patterns endpoint is:

{baseURL}/api/v1/agentx/{app_id}/friction/patterns?min_count={N}&limit={N}&start_date={}&end_date={}

Fix: Accept a full URL or make the path configurable. Suggested approach — add NewHTTPSourceWithURL(fullURL) that takes the complete endpoint URL, or add options:

source := frictionax.NewHTTPSource(baseURL,
    frictionax.WithSourcePath("/api/v1/agentx/myapp/friction/patterns"),
    frictionax.WithSourceAuth(func() string { return bearerToken }),
    frictionax.WithSourceParams(map[string]string{"start_date": "2026-01-01"}),
)

2. HTTPSource has no auth support

HTTPSource creates a bare http.Client{} with no authorization headers. SageOx AgentX requires JWT Authorization: Bearer headers on all authenticated endpoints.

Fix: Add auth option to HTTPSource (bearer token function, same pattern as WithAuth on the telemetry client).

3. No url redirect handling in PatternsResponse

Our AgentX endpoint may return a url field pointing to a pre-signed S3 URL for the full patterns JSON (for scale). Current HTTPSource.FetchPatterns() ignores this field.

Fix: After decoding PatternsResponse, check if url is set. If so, follow the redirect and decode the full response from S3. This is optional behavior — the inline patterns array is always valid when url is absent.

type PatternsResponse struct {
    Patterns  []PatternDetail `json:"patterns"`
    Total     int             `json:"total"`
    URL       string          `json:"url,omitempty"`       // pre-signed S3 URL
    ExpiresAt string          `json:"expires_at,omitempty"` // URL expiry
}

4. Telemetry submission path is hardcoded to ox-cli

client.go:88 hardcodes:

url := c.config.Endpoint + "/api/v1/cli/friction"

Third-party CLI tools using SageOx AgentX would submit to:

POST /api/v1/agentx/capture

with API key auth (X-API-Key header) and a different event envelope format (AgentX CaptureRequest wraps events differently from SubmitRequest).

Fix: This is the bigger lift. Options:

  • Option A: Add a WithSubmitPath(path) option to override the path
  • Option B (recommended): Add a SageOxSource / SageOxCollector that knows AgentX's API shape — translates FrictionEvent → AgentX CaptureEvent, uses API key auth, hits /capture

5. No "SageOx hosted" convenience constructor

Users who want the hosted SageOx backend should have a simple entry point:

f := frictionax.New(adapter,
    frictionax.WithSageOx("your-api-key"),  // sets endpoint, auth, paths
    frictionax.WithCatalog("mycli"),
)

This would configure:

  • Telemetry endpoint → https://api.sageox.ai with API key auth
  • Submit path → /api/v1/agentx/capture
  • Event translation → FrictionEvent → AgentX CaptureEvent format
  • Patterns source → /api/v1/agentx/{app_id}/friction/patterns

And the CLI equivalent:

# Fetch patterns from SageOx hosted backend
frictionax catalog build \
    --sageox-api-key sk_... \
    --sageox-app-id myapp \
    --catalog hand-crafted.json \
    --output catalog.json

Proposed Implementation Order

  1. HTTPSource auth + configurable path (unblocks pattern fetching from AgentX)
  2. PatternsResponse url redirect handling (future-proofs for S3 cached catalogs)
  3. WithSageOx convenience constructor (ergonomic hosted experience)
  4. AgentX capture adapter (telemetry submission to hosted backend)

Context

  • AgentX patterns endpoint: GET /api/v1/agentx/{app_id}/friction/patterns
  • AgentX capture endpoint: POST /api/v1/agentx/capture (API key in X-API-Key header)
  • Response format is wire-compatible with PatternsResponse (same PatternDetail fields)
  • See sageox-mono apps/api-go/internal/handlers/agentx/analytics.go for endpoint implementation

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions