Docs
The agent
A small collector that runs beside n8n, reads it read-only, and pushes signed metadata outbound. Includes how to tell whether it is working.
The agent is a standalone container you run next to your n8n. It reads n8n read-only, reduces each execution to metadata on your host, and pushes that to Obsevo over outbound HTTPS. It never opens a port to the internet and never receives a callback, so it works from inside a private network with no inbound firewall rule.
You need the three values from connecting an instance: the instance ID, the one-time secret, and your ingest URL.
Choose a read mode
The agent can read n8n through its REST API or straight from its database.
API mode (recommended)
Needs an n8n API key. This is the mode to use: it reports per-node output counts, which is what green-but-broken detection compares against.
docker run -d --name obsevo-agent --restart unless-stopped \
-e OBSEVO_INGEST_URL=https://ingest.example.com/ingest \
-e OBSEVO_INSTANCE_ID=<uuid> \
-e OBSEVO_INGEST_SECRET=<secret> \
-e OBSEVO_N8N_MODE=api \
-e OBSEVO_N8N_URL=http://n8n:5678 \
-e OBSEVO_N8N_API_KEY=<n8n api key> \
-v obsevo-agent-data:/data -e OBSEVO_CURSOR_FILE=/data/cursor \
ghcr.io/obsevo/obsevo-agent:latestA read-only n8n key is enough. The agent never writes through it — control actions are a separate, opt-in path that does not go through the agent at all.
DB mode
For installs where an API key is not practical. Use a SELECT-only role:
CREATE USER obsevo_ro WITH PASSWORD '…';
GRANT CONNECT ON DATABASE n8n TO obsevo_ro;
GRANT USAGE ON SCHEMA public TO obsevo_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO obsevo_ro;Then set OBSEVO_N8N_MODE=db and OBSEVO_N8N_DB_URL instead of the two API
variables.
Verify it's working
This is where setups quietly fail, so check it rather than assuming.
Expect the first runs within one poll interval — 30 seconds by default. The agent only reports executions that finish after it starts, so if the workflow runs hourly, nothing will appear until it next runs. Trigger a workflow manually if you want an immediate answer.
Check the agent's own logs first:
docker logs obsevo-agent --tail 50Then confirm the credentials are accepted, without waiting for a run:
curl -H 'authorization: Bearer <event key>' https://ingest.example.com/ingest/verifyA 200 with your instance name means the key and the URL are both right.
When nothing arrives
| Symptom | Cause | Fix |
|---|---|---|
401 invalid signature | The secret does not match the instance | Rotate the secret on the instance and restart the agent |
401 stale or invalid timestamp | Host clock drift beyond ±5 minutes | Fix NTP on the agent host — the signature covers the timestamp |
401 unknown instance | Wrong instance ID, or it was deleted | Re-check the ID against the dashboard |
| Connection refused or DNS failure | Wrong ingest URL, or ingest.<domain> has no DNS record | Confirm the hostname resolves from the agent host |
| Agent logs look clean, dashboard shows nothing | n8n has had no executions since the agent started | Run a workflow manually |
403 or empty results from n8n in API mode | The n8n API key lacks read access | Issue a key with read scope |
| Instance shows as down after working | The agent stopped, or the host lost outbound access | docker ps, then check egress |
All options
| Env var | Default | Notes |
|---|---|---|
OBSEVO_INGEST_URL | — | required |
OBSEVO_INSTANCE_ID | — | required (uuid) |
OBSEVO_INGEST_SECRET | — | required |
OBSEVO_N8N_MODE | — | api or db |
OBSEVO_N8N_URL / OBSEVO_N8N_API_KEY | — | API mode |
OBSEVO_N8N_DB_URL | — | DB mode |
OBSEVO_POLL_INTERVAL_MS | 30000 | poll cadence |
OBSEVO_SNAPSHOT_EVERY | 10 | workflow snapshot every N cycles |
OBSEVO_MAX_BATCH | 200 | executions per cycle (max 500) |
OBSEVO_CURSOR_FILE | .obsevo-agent-cursor | persist it, for incremental resume |
OBSEVO_AGENT_VERSION | 0.0.0 | reported in heartbeats |
And for real-time capture, which is off unless a token is set:
| Env var | Default | Notes |
|---|---|---|
OBSEVO_HOOK_TOKEN | — | Setting it enables the hook receiver. Minimum 16 characters |
OBSEVO_HOOK_HOST | 127.0.0.1 | Bind address. Keep it off the public internet |
OBSEVO_HOOK_PORT | 5680 | Port the receiver listens on |
OBSEVO_HOOK_MAX_BYTES | 16777216 | Largest accepted hook body |
Mount a volume for OBSEVO_CURSOR_FILE. Without it, a restarted agent has no
memory of where it got to.
What actually leaves your host
Per node: status, timing, item counts, and error text. For AI nodes: the model name, the provider, token counts, and a whitelisted set of scalar tuning parameters.
Never: execution payloads, prompt or completion content, credentials, or arbitrary node parameters. Full detail is on the security page.