Skip to content
sigiro[.]com

Quickstart

Run sigiro with one docker command, point OpenTelemetry at it, then ask it what changed and why. Five minutes, no collector, no config.

sigiro is one process. Start it, send it OTLP, then query it. There is no collector to deploy and no configuration file.

1. Run it

bash
docker run -p 4317:4317 -p 4318:4318 -p 9999:9999 ghcr.io/sigiroai/sigiro

Three ports, each doing one thing:

PortProtocol
4317OTLP over gRPC
4318OTLP over HTTP
9999the query and investigate API

First start downloads its query extensions and can take 30–90 seconds. After that it is instant. Data lands in SIGIRO_DATA_DIR (/var/lib/sigiro in the image, ~/.local/share/sigiro for a local binary), so add -v sigiro-data:/var/lib/sigiro to keep it across container restarts.

A self-hosted server runs in open mode: no per-request authentication. Put it behind a tailnet, a private network, or a reverse proxy — the network is the security boundary. Tenant keys exist only for the hosted service.

2. Send it telemetry

Any OpenTelemetry SDK or collector already in your stack works unchanged — point the standard environment variables at sigiro:

bash
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \
OTEL_SERVICE_NAME=checkout \
  <your-app-start-command>

If your code is not instrumented yet, don't do it by hand — hand a coding agent the prompt in the AI instrumentation guide.

Confirm it arrived:

bash
curl http://localhost:9999/v1/services

3. Ask what changed

anomalies is the loop's entry point. It returns shifts that deviate from each service's own recent baseline — not threshold breaches — ranked biggest-shift first, with cross-signal shifts grouped under one incident_id.

bash
sigiro anomalies
sigiro anomalies --service checkout

Nothing to configure: there are no thresholds to pick, and a service that is chronically slow but stable is not an anomaly.

4. Ask why

investigate returns one structured evidence block for a service and window: ranked findings, error counts, per-operation error breakdowns by error.type, per-model LLM stats, sampled spans and deduplicated log patterns — and a ready-to-run SQL query on every row so the next question is a copy-paste away.

bash
sigiro investigate checkout
sigiro investigate checkout --from $(date -v-1H +%s) --grep POST

Over HTTP, for an agent:

bash
curl -X POST http://localhost:9999/v1/investigate \
  -H 'content-type: application/json' \
  -d '{"service":"checkout"}'

5. Drill with SQL

When the evidence block isn't enough, every row in it hands you the SQL to go deeper. Your telemetry is just tables:

bash
sigiro query "
  SELECT service_name, count(*) AS errors
  FROM sigiro_spans
  WHERE status_code = 2 AND timestamp > now() - INTERVAL '1 hour'
  GROUP BY 1 ORDER BY errors DESC"

Tables are sigiro_spans, sigiro_logs, sigiro_log_templates, sigiro_metrics_gauge / _sum / _histogram / _exp_histogram, sigiro_profiles and sigiro_anomalies. status_code is the OTLP enum, so 2 is an error. Bound timestamp in every query — sigiro query refuses an unbounded scan across edges unless you pass --full-scan, and it is the difference between reading one file on disk and reading all of them.

The body is the raw SQL, not JSON:

bash
curl -X POST http://localhost:9999/v1/query \
  --data "SELECT count(*) FROM sigiro_spans WHERE timestamp > now() - INTERVAL '1 hour'"

Every command prints pretty JSON — the same bytes whether a human or jq is reading, with no format to choose and no TTY detection to reason about.

Other commands

bash
sigiro status             # server health
sigiro diagnose          # debug sigiro using sigiro's own telemetry
sigiro fetch-extensions  # pre-download query extensions before an offline deploy
sigiro healthcheck       # exit 0 only when ready (the container's HEALTHCHECK)

Next