Custom Extensions

Extension API

Custom extensions communicate with RebelOps through window.postMessage. This works in browser iframes and in the native in-app web view via a compatibility polyfill.

Transport Contract

The host and extension exchange JSON messages. The web runtime uses iframe postMessage directly; the native runtime polyfills window.parent.postMessage and forwards payloads to Flutter.

Message Shape
{
  "type": "request | response | event | tool_call | tool_response",
  "id": "unique-message-id",
  "method": "optional.method.name",
  "data": {},
  "timestamp": 1730000000000
}

Keep id unique per request/tool call so responses can be correlated.

Recommended Initialization

JavaScript
const REBELOPS_ORIGIN = 'https://web.rebelops.app'

function handleRebelOpsMessage(message) {
  switch (message?.type) {
    case 'tool_call':
      return handleToolCall(message)
    case 'response':
      return handleResponse(message)
    case 'event':
      return handleEvent(message)
    default:
      return
  }
}

window.addEventListener('message', (event) => {
  // Enforce in production for web-hosted extensions:
  // if (event.origin !== REBELOPS_ORIGIN) return
  handleRebelOpsMessage(event.data)
})

function sendToRebelOps(message) {
  window.parent.postMessage(message, REBELOPS_ORIGIN)
}

Tool Call Flow

When RebelOps invokes extension logic, your extension receives a tool_call and should reply with tool_response.

{
  "type": "tool_call",
  "id": "call-123",
  "tool": "create_task",
  "parameters": { "title": "Draft release notes" },
  "context": {
    "organizationId": "org-123",
    "projectId": "proj-456",
    "userId": "user-789"
  },
  "timestamp": 1730000000000
}

Error Response Format

Error Response
{
  "type": "tool_response",
  "id": "call-123",
  "success": false,
  "error": {
    "code": "TOOL_ERROR",
    "message": "Human-readable error",
    "details": {}
  },
  "timestamp": 1730000000500
}

Security Requirements

  • Validate event.origin before processing inbound messages.
  • Use HTTPS extension sources.
  • Never trust message payloads without validation.
  • Keep permission and authorization checks server-side in your extension backend where applicable.

Current Runtime Status (Updated)

  • Web host bridge sends and receives JSON payloads via iframe postMessage.
  • Native web view polyfills parent postMessage and forwards payloads to Flutter handler rebelopsPostMessage.
  • Native bridge currently returns a generic response echo for forwarded payloads; advanced host methods should be treated as evolving contracts.

Build integrations around postMessage transport and explicit tool call handling first; keep method-specific integrations versioned and defensive.

© 2026 Mironika LLC