Skip to content

Satellites

Satellites are project-level JSON-RPC integrations that are owned and configured by the project team. They are useful when a project needs to connect Protokol workflows to a custom service without publishing an integration to the marketplace.

Satellites are not marketplace integrations. They are only visible in the Developer section of the project where they are created, and they are only available to users in that project.


How Satellites Work

A satellite has two parts:

Part Purpose
Template Operational metadata: ID, label, JSON-RPC endpoint URL, optional health check URL, optional logs URL, auth type, and timeout.
Schema version Versioned capabilities: permissions, JSON-RPC commands, and workflow nodes.

The template stores the active schema versions for the two platform environments:

Environment Template field
Development dev_version
Live live_version

Deploying a schema version stores that schema's schema_version string in one of those fields. Rolling back is the same operation: deploy an older schema_version to dev or live.

When Protokol calls the satellite, it sends the active environment in the X-Env header. The satellite can use that header to route to development or live behavior on its side.


Transport

Satellites use JSON-RPC over HTTP. A satellite exposes one JSON-RPC endpoint, and Protokol proxies command execution to that endpoint.

The public platform command endpoint is:

POST /satellites/{satellite_id}/commands/{command}/execute

The SDK exposes this through Satellites.execute().

The satellite implementor does not need to create separate HTTP endpoints for every command. The schema maps platform command names to JSON-RPC methods.


Authentication

Satellites support:

Auth type Behavior
bearer Protokol injects Authorization: Bearer <secret> when calling the satellite.
api_key Protokol injects the configured custom header name with the configured secret.

Secrets are provided by the user, encrypted at rest, decrypted at runtime, and injected only when requests are sent to the satellite.

For api_key, auth_config.header_name is required.


Platform Headers

When Protokol calls a satellite, it resolves platform auth and authorization first, then forwards execution context through headers.

Common headers include:

Header Purpose
X-Env Current platform environment: dev or live.
X-Claims-Entity-Type Claim entity type, for example user or service, when available.
X-Claims-Entity-Id Stable authenticated actor id. Satellites should use this when they need the current user/service id.
X-Claims-Entity-Name Claim entity display name when available.
X-Claims-Entity-Prn PRN pointer for the authenticated caller when available.
X-Session Temporary compatibility header that mirrors the caller PRN for satellite runtimes that already read session context.
X-Request-UUID Request correlation ID.

The exact command input is sent as JSON-RPC params by the platform runtime. The same caller PRN is also included in JSON-RPC context as caller_prn, and split claim entity fields are included under claims_entity when available.


Permissions

The schema can export permissions. Exported permissions are made available in the platform RBAC system and can be assigned to roles.

Permission keys are generated by Protokol:

{action} external::{satellite_id}

For example:

execute external::crm-satellite
read_resource external::crm-satellite

Commands are protected by permissions. Each command can define a permission_action; if omitted, the command name is used as the action.

If a permission is removed from a later schema version and it is still assigned to a role, background cleanup can remove stale assignments later. Runtime checks only allow commands whose required permission currently exists and is assigned.


Health Checks

A template can define health_check_url. The consolidation service checks satellite health every 60 seconds.

Health status is shown in the Developer UI. There are no platform rate limits for these checks because the satellite is an external project-owned service.


Logs

A template can define logs_url. The Developer UI can load logs from the satellite through Protokol.

When Protokol requests logs, it sends the since query parameter:

GET {logs_url}?since=2026-06-22T05%3A25%3A00.000Z

Satellite implementors should return logs since that timestamp. JSON responses are passed through. Plain text responses are wrapped by Protokol.


Resource Resolver

Satellites can resolve project resources through the existing platform Resource Resolver flow.

The PRN format is standardized:

prn:integration:external::<satellite_id>:<path>

Users still call the normal Resource Resolver endpoint. Protokol recognizes the external satellite integration PRN, resolves the satellite and active schema internally, then proxies the resolver call to the satellite JSON-RPC command named resolve_resource.

resolve_resource is a reserved convention. Satellite schemas should expose a jsonrpc_commands entry with name: "resolve_resource" when they support resource resolution; schemas do not configure a separate resolver command.


Workflow Nodes

Satellites can expose workflow operation nodes through workflownodes.

In v1:

  • satellites can provide workflow nodes
  • satellites cannot provide workflow events
  • satellites cannot provide render events
  • satellites do not use onboarding schema
  • satellites do not use settings schema

Each workflow node maps to a satellite command. When the workflow executes that node, Protokol calls:

POST /satellites/{satellite_id}/commands/{command}/execute

Template Example

{
  "id": "crm-satellite",
  "label": { "en_US": "CRM Satellite" },
  "description": { "en_US": "Project-owned JSON-RPC satellite for CRM workflows." },
  "icon": "satellite",
  "jsonrpc_endpoint_url": "http://host.docker.internal:8787/jsonrpc",
  "health_check_url": "http://host.docker.internal:8787/health",
  "logs_url": "http://host.docker.internal:8787/logs",
  "auth_type": "bearer",
  "auth_config": {
    "secret": "dev-secret"
  },
  "timeout_ms": 30000
}

For API key authentication:

{
  "auth_type": "api_key",
  "auth_config": {
    "header_name": "X-Api-Key",
    "secret": "dev-secret"
  }
}

Schema Example

{
  "schema_version": "2026-06-22.crm.v1",
  "schema": {
    "name": "crm-satellite",
    "description": "CRM satellite schema for JSON-RPC command, resource resolver, and workflow node execution."
  },
  "permissions": [
    {
      "action": "execute",
      "label": { "en_US": "Execute CRM satellite commands" },
      "description": { "en_US": "Allows running JSON-RPC commands exposed by the CRM satellite." }
    },
    {
      "action": "read_resource",
      "label": { "en_US": "Resolve CRM satellite resources" },
      "description": { "en_US": "Allows resolving PRNs owned by the CRM satellite." }
    }
  ],
  "jsonrpc_commands": [
    { "name": "echo", "method": "echo", "permission_action": "execute" },
    { "name": "add", "method": "math.add", "permission_action": "execute" },
    { "name": "uppercase", "method": "workflow.uppercase", "permission_action": "execute" },
    { "name": "resolve_resource", "method": "resource.resolve", "permission_action": "read_resource" }
  ],
  "workflownodes": [
    {
      "name": "satellite.crm.uppercase",
      "label": { "en_US": "Uppercase Text" },
      "description": { "en_US": "Converts input text to uppercase using the CRM satellite." },
      "icon": "satellite",
      "command": "uppercase",
      "inputs": [
        {
          "name": "text",
          "type": "string",
          "required": true,
          "label": { "en_US": "Text" },
          "description": { "en_US": "Text to transform." }
        }
      ],
      "outputs": [
        { "name": "text", "type": "string" },
        { "name": "uppercase", "type": "string" },
        { "name": "length", "type": "number" }
      ]
    }
  ]
}

Schema Fields

Field Required Description
schema_version Yes Human-readable schema version label.
schema No Metadata for the satellite schema. This is not onboarding or settings schema.
permissions No Permission actions exported into platform RBAC.
jsonrpc_commands Yes Commands the platform can execute through JSON-RPC.
workflownodes No Workflow operation nodes exposed in the workflow canvas.

jsonrpc_commands

Field Required Description
name Yes Stable platform command name. Used in /commands/{command}/execute.
method Yes JSON-RPC method sent to the satellite endpoint.
permission_action No Permission action required to execute the command. Defaults to name.

workflownodes

Field Required Description
name Yes Stable internal workflow node identifier.
label Yes User-facing label in the workflow canvas.
description No User-facing description in the workflow node palette.
icon No Node icon. Use satellite for the built-in antenna icon.
command Yes Satellite command executed by this node.
inputs No Input fields rendered in the workflow node configuration.
outputs No Output fields available to downstream workflow nodes.

SDK Example

import { Satellites } from '@ptkl/sdk/beta';

const satellites = new Satellites({
  host: 'https://lemon.protokol.io/luma/integrations',
  token: process.env.PROJECT_API_TOKEN,
  env: 'dev',
});

const created = await satellites.create({
  template: {
    id: 'crm-satellite',
    label: { en_US: 'CRM Satellite' },
    jsonrpc_endpoint_url: 'http://host.docker.internal:8787/jsonrpc',
    auth_type: 'bearer',
    auth_config: { secret: 'dev-secret' },
  },
  schema: {
    schema_version: '2026-06-22.crm.v1',
    jsonrpc_commands: [
      { name: 'echo', method: 'echo', permission_action: 'execute' },
    ],
  },
});

await satellites.deploy(created.id, {
  env: 'dev',
  schema_version: '2026-06-22.crm.v1',
});

const response = await satellites.execute(created.id, 'echo', {
  inputs: { message: 'hello' },
  context: { source: 'docs' },
});