Skip to main content

Creating an Agent

This guide walks through creating an agent application based on io-oidis-connector. An agent is a standalone process that connects to Oidis Hub via reverse WebSocket tunnel, enabling remote management of devices behind firewalls.

For architectural details, see Connector Overview and Request Forwarding.

Prerequisites​

  • Oidis Builder CLI (oidis command available)
  • An Oidis Hub instance (local or remote) for agent registration
  • Hub agent token (created in Hub GUI or API)

1. Project Setup​

Create a new project that depends on io-oidis-connector:

package.conf.jsonp​

Io.Oidis.Builder.DAO.Resources.Data({
$interface: "IProjectSolution",
name: "io-oidis-my-agent",
version: "2026.0.1",
loaderClass: "Io.Oidis.MyAgent.Loader",
dependencies: {
"io-oidis-connector": "git+https://gitlab.com/oidis/io-oidis-connector.git#develop"
}
});

Loader​

Create the main loader at source/typescript/Io/Oidis/MyAgent/Loader.ts:

import { Loader as Parent } from "@io-oidis-connector/Io/Oidis/Connector/Loader.js";

export class Loader extends Parent {

protected async afterLoad() : Promise<void> {
await super.afterLoad();
// Custom initialization after agent registration
}
}

The parent Loader handles all agent mode initialization — Hub connection, registration, heartbeat, and request forwarding.

2. Adding Custom Connectors​

To expose custom functionality through the agent tunnel, create connectors with @Extern() methods:

import { BaseConnector } from "@io-oidis-localhost/Io/Oidis/Localhost/Primitives/BaseConnector.js";
import { Extern } from "@io-oidis-localhost/Io/Oidis/Localhost/Primitives/Decorators.js";
import { ResponseFactory } from "@io-oidis-localhost/Io/Oidis/Localhost/HttpProcessor/ResponseApi/ResponseFactory.js";
import { IResponse } from "@io-oidis-localhost/Io/Oidis/Localhost/Interfaces/IResponse.js";

export class SensorConnector extends BaseConnector {

@Extern()
public ReadTemperature($callback : IResponse) : void {
const response : IResponse = ResponseFactory.getResponse($callback);
// Read from hardware sensor
response.Send({ celsius: 22.5, timestamp: Date.now() });
}

@Extern()
public GetDeviceStatus($callback : IResponse) : void {
const response : IResponse = ResponseFactory.getResponse($callback);
response.Send({ online: true, uptime: process.uptime() });
}
}

A connector file containing @Extern( is added to the generated block of ForceCompile.ts by every build, so it needs no manual registration. A manual import outside that block, as below, is only needed for a class the build does not detect (for example one that only inherits its @Extern methods from a base class in another file):

export { SensorConnector } from "./Connectors/SensorConnector.js";

Methods decorated with @Extern() are automatically discoverable by the LCP resolver. When the agent registers with Hub, these methods become callable through the tunnel (subject to Hub's method whitelisting).

3. Configuration​

private.conf.jsonp (Development)​

Io.Oidis.Builder.DAO.Resources.Data({
$interface: "IProjectSolution",
domain: {
ports: { http: 8088 },
ssl: false
},
agent: {
hub: "dev",
name: "my-sensor-agent",
poolName: "sensors",
tag: "Temperature sensor - Lab A",
credentials: {
userName: "agent-user",
authToken: "your-agent-token"
},
configuration: {
SENSOR_TYPE: "DHT22",
LOCATION: "lab-a"
},
disableMetadataEnv: false
},
heartbeat: {
enabled: true,
exitOnError: true,
period: 30000,
timeout: 10000,
restartDelay: 5000
},
hubLocations: {
prod: "https://hub.oidis.io",
eap: "https://hub.eap.oidis.io",
dev: "http://localhost:9010"
}
});

Key Configuration Fields​

FieldDescription
agent.hubHub URL or alias (prod, eap, dev) — resolved via hubLocations
agent.nameDisplay name in Hub's agent registry
agent.poolNameAgent pool for grouping (default: "Default")
agent.tagHuman-readable description
agent.configurationCustom metadata key-value pairs (sent during registration)
agent.disableMetadataEnvSet true to omit process.env from metadata
heartbeat.exitOnErrorExit on heartbeat failure — use with systemd/PM2 restart policy
heartbeat.periodInterval between status updates (ms)

4. Running the Agent​

Development (Server Mode)​

oidis dev

Starts the connector as a local HTTP server on the services port. Useful for testing connectors without Hub.

Development (Agent Mode)​

oidis dev -- agent --hub=dev --name=test-agent

Connects to the development Hub instance. CLI arguments override config values.

Production​

oidis build app

Build the application, then run the built artifact with the agent argument. The --hub, --name, --user, and --token arguments can be passed at runtime:

./my-agent agent --hub=prod --name=sensor-lab-a --user=agent-user --token=secret

5. Deployment​

Deploy Configuration​

Add deployment targets in bin/project/configs/deploy.jsonp:

Io.Oidis.Builder.DAO.Resources.Data({
$interface: "IProjectSolution",
deploy: {
updates: {
Linux: {
location: {
releaseName: "Linux",
platform: "app-linux-nodejs",
version: "latest"
},
agents: [
{ name: "hub-agent:my-agent-prod", profile: "prod" },
{ name: "hub-agent:my-agent-dev", profile: "dev" }
],
app: {
config: "path/to/production.config.jsonp",
args: ["agent"]
}
}
}
}
});

Process Management​

For production deployments, use a process manager to handle automatic restarts:

  • systemd (Linux) — configure Restart=always in the service unit
  • PM2 (cross-platform) — pm2 start ./my-agent -- agent --hub=prod

Set heartbeat.exitOnError: true so the agent process exits on heartbeat failure, allowing the process manager to restart it.

Supported Platforms​

PlatformBuild Solution
Linux x64app-linux-nodejs
Windows x64app-win-nodejs
ARM 32-bitarm solution
ARM 64-bit (aarch64)arm64 solution

6. Verifying the Agent​

Once the agent is running and connected to Hub:

  1. Open Hub GUI → Agents section
  2. Verify the agent appears with correct name, pool, and tag
  3. Check the agent status shows "active"
  4. Test forwarded requests through Hub's agent forwarding interface

The agent's metadata (system fingerprint, platform, custom configuration) is visible in Hub's agent details view.


See also: Connector Overview | Request Forwarding | Connectors Reference | Common Patterns