Skip to main content

Agents

The agent is the part of Reporting that runs on your infrastructure. It holds database credentials, executes queries, renders documents, and delivers them. The control plane never touches your data.

Deployment​

Docker​

docker run -d --name rynko-agent \
--restart unless-stopped \
-e RYNKO_API_KEY=your_agent_key \
-v $(pwd)/config:/app/config \
-v $(pwd)/data:/app/data \
ghcr.io/delivstat/rynko-reporting-agent:latest

Or with docker compose, which is the better option once you have secrets and volumes to manage:

services:
agent:
image: ghcr.io/delivstat/rynko-reporting-agent:latest
restart: unless-stopped
environment:
RYNKO_API_KEY: ${RYNKO_API_KEY}
PG_PASSWORD: ${PG_PASSWORD}
volumes:
- ./config:/app/config
- ./data:/app/data
ports:
- "8080:8080" # local health check only

Archive (no Docker)​

For Windows servers and locked-down Linux hosts:

  1. Download and extract the release archive
  2. Edit config/agent.yaml
  3. Run ./start.sh (Linux) or start.bat (Windows)

The archive bundles its own Node runtime. There is no JVM and no system-wide install.

rynko-reporting-agent/
├── bin/agent # agent binary (includes the rynko-run CLI)
├── config/agent.yaml # your configuration
└── data/ # SQLite metadata, template cache, generated documents

Configuration​

Everything lives in config/agent.yaml. Values may reference environment variables with ${VAR_NAME}, which is how credentials should be supplied.

server:
apiKey: ${RYNKO_API_KEY} # from agent registration
apiUrl: https://api.rynko.dev
port: 8080 # local health check port

datasources:
production-erp:
type: oracle
host: 10.0.1.50
port: 1521
serviceName: ERPDB.example.com
user: report_reader
password: ${ORACLE_PASS}
pool:
min: 2
max: 10
queryTimeout: 60000

distribution:
smtp:
host: smtp.company.com
port: 587
secure: true
user: [email protected]
password: ${SMTP_PASS}
from: [email protected]
fromName: "Rynko Reports"

database:
path: ./data/agent.db # agent-local SQLite metadata

storage:
type: filesystem
path: ./data/documents
retentionDays: 30 # local document retention
archive: false # also upload documents to Rynko for long-term storage

offline:
templateCachePath: ./data/templates
maxQueueSizeMb: 500

scheduling:
timezone: UTC
maxConcurrentRuns: 3

updates:
autoUpdate: false

Document retention and archiving​

Generated documents are written to the agent's local filesystem and swept after storage.retentionDays (a cleanup pass runs at startup and every six hours). The webapp's download button fetches them from the agent on demand, so recent reports are viewable without any object storage at all.

Set storage.archive: true to also upload each generated document to Rynko for long-term retention. An individual report can force this on regardless of the agent default.

Connectivity​

The agent opens one outbound HTTPS connection and holds it open as a server-sent events stream. Configuration changes, template updates, and run commands are pushed down it. Results and status are posted back over ordinary HTTPS.

This means:

  • No inbound firewall rules. Nothing needs to reach the agent from outside.
  • No VPN or IP allowlist.
  • Egress to one host. If you filter outbound traffic, allow api.rynko.dev over 443.

If the connection drops, the agent reconnects with backoff. Scheduled runs continue against the local cache while it is down, and their results sync when it returns.

Security model​

Credentials never leave your network. Database passwords, SMTP passwords, and webhook URLs exist only in agent.yaml on your host. The control plane stores the connection shape — driver, host, port, database name — so the UI can show you what a datasource is, but never the secret.

Result sets never leave your network unless you distribute them. Query output goes straight into the local renderer. What the control plane records is metadata: run status, duration, row count, and any error.

Credentials pushed from the webapp are end-to-end encrypted. Distribution channel credentials entered in the UI are encrypted to the target agent's public key before transmission. Rynko cannot read them in transit or at rest.

Agent keys are pinned. Each agent's key has a fingerprint. If a key is used from an unexpected agent identity, the control plane raises an alert rather than silently accepting it.

Operating the agent​

Health​

The agent exposes a local health endpoint on server.port:

curl http://localhost:8080/health

Agent status, last heartbeat, and per-datasource connection pool health are also visible in Reporting → Agents in the webapp.

The CLI​

rynko-run executes a report and exits. It shares agent.yaml and the agent's connection pools, which makes it the right tool for system cron, Windows Task Scheduler, and CI pipelines.

rynko-run --list

rynko-run --report monthly-sales \
--params '{"region":"APAC","date_from":"2026-09-01"}'

rynko-run --report monthly-sales --dry-run # run the query, skip the document
rynko-run --report monthly-sales --no-distribute # generate, don't deliver
rynko-run --report monthly-sales --output ./out.xlsx

Reports are addressable by slug, short ID (rpt_a1b2c3d4), or UUID.

Upgrades​

Set updates.autoUpdate: true to let the agent update itself, or leave it off and pull a new image or archive on your own change schedule. Pin the image tag in production rather than tracking latest.

How many agents do I need?​

One agent can serve many datasources, so most sites need one. Add more when you have networks that cannot reach each other, want to isolate environments, or need to spread report load across hosts.

Your subscription tier caps the number of agents — see Limits & Quotas.