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 (
oidiscommand 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
| Field | Description |
|---|---|
agent.hub | Hub URL or alias (prod, eap, dev) — resolved via hubLocations |
agent.name | Display name in Hub's agent registry |
agent.poolName | Agent pool for grouping (default: "Default") |
agent.tag | Human-readable description |
agent.configuration | Custom metadata key-value pairs (sent during registration) |
agent.disableMetadataEnv | Set true to omit process.env from metadata |
heartbeat.exitOnError | Exit on heartbeat failure — use with systemd/PM2 restart policy |
heartbeat.period | Interval 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=alwaysin 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
| Platform | Build Solution |
|---|---|
| Linux x64 | app-linux-nodejs |
| Windows x64 | app-win-nodejs |
| ARM 32-bit | arm solution |
| ARM 64-bit (aarch64) | arm64 solution |
6. Verifying the Agent
Once the agent is running and connected to Hub:
- Open Hub GUI → Agents section
- Verify the agent appears with correct name, pool, and tag
- Check the agent status shows "active"
- 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