- 1.6.0
- 1.3.6
- 1
- observer-agent-7c9f5d8b6-x2kqp
- 48.21 MB
- 76h 12m 09s
ProductAgent
Watch private systems without opening a port.
The open-source agent runs next to your databases and internal services, checks them from inside and dials out with the status. Credentials never leave the host.
Copy the command
The console fills in the agent key.
Run it next to your services
A container, a pod, a service unit or a plain binary.
Watch it connect
The console shows it connected on its first heartbeat.
docker run -d \
--name observer-agent \
--hostname "$(hostname)" \
--restart unless-stopped \
-v observer-agent-buffer:/data \
-e AGENT_KEY="${AGENT_KEY}" \
-e CLOUD_SERVER_URL="https://use.observer" \
-e BUFFER_PATH="/data/observer-agent-buffer.db" \
ghcr.io/useobserver/agent:latest[2026-10-06T09:12:01.204Z] [INFO] Debug dashboard listening on http://127.0.0.1:10101[2026-10-06T09:12:01.611Z] [INFO] Successfully fetched metric definitions (1)[2026-10-06T09:12:05.932Z] [INFO] Fetching metric: http metric=3f2a9c1e-5b7d-4e21-9a0c-6d4f8e2b1a73
Boundary
Your credentials stay where they are.
Observer never needs a way into your network, and never holds a password. Observer learns how your systems are doing, never how to log in to them.
On your host
Credentials live in the agent's environment. The agent reads them when a probe runs, and reduces every response, row and series to one number.
# observer-agent.env, on the host ORDERS_DB_URL=postgres://monitor:••••••@10.0.4.12:5432/orders LEDGER_API_TOKEN=Bearer ••••••••••••
In Observer
The check stores the name of the variable, never its value. A header that looks like a credential is refused in the plain headers field when you save.
[
{
"source_type": "database",
"source_config": {
"kind": "postgres",
"connection_string_ref": "ORDERS_DB_URL",
"query": "SELECT count(*) FROM jobs WHERE state = 'pending'"
}
},
{
"source_type": "http",
"source_config": {
"url": "https://ledger.internal/healthz",
"header_refs": { "Authorization": "LEDGER_API_TOKEN" }
}
}
]On the wire
The reading, its status, and a reason code when there was nothing to read. Plus a heartbeat every 30 seconds with the agent's own health, its host name and the names of any custom probes.
POST /api/agent/receiver/batch
[
{
"metric_id": "8b71d044-2c9e-4f3a-b815-7e0d9c4a6f12",
"value": 42,
"timestamp": "2026-10-06T09:14:02.118Z",
"status": "healthy"
},
{
"metric_id": "e2c47b18-9d3a-4b70-8f25-1c6e4a9b0d37",
"value": 0,
"timestamp": "2026-10-06T09:14:05.402Z",
"status": "no_data",
"reason": "unexpected_status:503"
}
]versionbuildhostnameuptime_secondsqueue_depthqueue_oldest_age_secondssource_types_activecustom_probesDirection
Every connection starts on your side.
The agent calls out over HTTPS with its key and refuses redirects, so the key never follows a hop. Nothing in your network listens for Observer.
References
Every secret is a name.
Connection strings, tokens, client certificates, secret headers and gRPC metadata are all set as env var names. If one is missing, the check reports a reason code, never a value.
Opt in
Logs only if you turn them on.
Log broadcast is off by default. Switched on, it streams the agent's own log lines, with Prometheus queries hashed.
On request
CloudWatch names when you browse.
When you browse CloudWatch metrics in the console, the agent lists them with the host's AWS credentials and returns metric names and dimensions. No values.
Changes
Change a check. The agent has it in seconds.
Edit a threshold or add a check in the console, or apply observer.yaml from CI. The agent hears about it on its next check-in, every 30 seconds. No redeploy, no restart.
Heartbeat
Nothing changed. The agent keeps its probes running.
You save a change
A new threshold, a new check or a different query, in the console or from observer.yaml.
Next heartbeat
The reply says the definitions changed, so the agent fetches the new set right away.
First reading
The changed check runs within seconds. Unchanged checks keep their schedule.
Only what changed
Running checks keep their rhythm.
Unchanged checks keep their timers. A changed one restarts and takes its first reading straight away.
Backstop
A full refresh every five minutes.
agent 1.6.0If a change signal is ever missed, the regular fetch catches it. A freshly started agent polls every 30 seconds until its first checks arrive.
Dashboard
See what it sees, from the host.
By default each agent serves a read-only dashboard on its own machine: each probe's last value and status, the link to Observer, the queue and the recent log.
Local by default
Bound to the loopback address.
:10101Exposing it to other machines needs a bearer token; without one the agent stays on 127.0.0.1.
Masked
Settings you can screenshot.
Only agent settings are shown, every value masked, and the dashboard's own token never at all.
Outages
Readings wait out an outage.
When Observer is unreachable, readings queue on disk and go out in order once the link is back. Observer, meanwhile, notices the silent agent and can alert you.
On the host, twenty minutes in
How the queue behaves
- Capacity
- 10,000 rows, adjustable
- When full
- Oldest rows go first
- Retry
- 1 s, doubling to 5 min
- On reconnect
- Drains oldest first
Status changes are queued the moment they happen, so the history fills in with the right times once the link is back.
Run it
One small process, wherever your services are.
A container image, a Kubernetes manifest, a systemd unit or a single binary. One agent covers every check on its network.
Platforms
Linux, macOS and Windows.
Standalone binaries for Linux and macOS on x64 and arm64, and Windows on x64, for hosts that cannot pull an image.
Also on the host
A relay for jobs with no way out.
opt inCron jobs on a private network can ping the agent, which forwards their heartbeats over its own connection.
Open source
Read every line it runs.
Apache 2.0 on GitHub. Each heartbeat reports the build it came from, so the agents list can tell an official image from a modified one.
Plans
Agents per organization.
- Free
- 1
- Starter
- 3
- Pro
- 10
- Business
- 25
- Enterprise
- Unlimited