The agent can respond to human comments on a remediation pull request. It re-investigates (the PR diff, the original alert/checkpoint context, and live Kubernetes / Prometheus / logs) and replies in the PR conversation:
@opsgentic-agent give me evidence) → it investigates and
answers with concrete evidence.GitHub only. PR conversation comments only (not review/code-line comments). The agent never merges — merging stays a human gate.
GitHub PR comment
→ POST /webhook/github (verify HMAC, filter, dedup)
→ enqueue (worker)
→ assemble context (run/checkpoint or PR body, comments, base...branch diff)
→ PR-responder agent (read-only: kubernetes + prometheus + github + logs)
→ reply (+ commit to the PR branch if it agrees with a suggestion)
For each issue_comment.created on a PR, after excluding the agent’s own comments, it
replies when either:
@opsgentic-agent), orA GitHub App has no real @-mentionable handle: typing
@opsgentic-agentwill not autocomplete or turn into a link, and that is expected. The webhook matches the literal text in the comment body, so it still triggers. The handle is configured byGITHUB_AGENT_HANDLE(defaultopsgentic-agent).
Three parts: expose the webhook endpoint publicly, configure the GitHub App, and set the
opsgentic secret/config. The application listens on POST /webhook/github.
/webhook/github over public HTTPSGitHub must reach the endpoint from the public internet. On a private cluster (no public IP)
use an outbound tunnel. Below is Tailscale Funnel; any tunnel that yields a public HTTPS
URL works (Cloudflare Tunnel, ngrok, …) — just point it at the opsgentic Service (:80).
Tailscale Funnel (manifest: deploy/manifests/webhook/ingress-tailscale.yaml)
tag:k8s-operator:
helm repo add tailscale https://pkgs.tailscale.com/helmcharts && helm repo update
helm upgrade --install tailscale-operator tailscale/tailscale-operator \
--namespace tailscale --create-namespace \
--set-string oauth.clientId=<id> --set-string oauth.clientSecret=<secret> \
--set-string operatorConfig.defaultTags="tag:k8s-operator"
Get the OAuth client at admin console → Settings → OAuth clients.
tag:k8s by
default — Funnel must target tag:k8s, not tag:k8s-operator:
"tagOwners": {
"tag:k8s-operator": [],
"tag:k8s": ["tag:k8s-operator"],
},
"nodeAttrs": [
{ "target": ["tag:k8s"], "attr": ["funnel"] },
],
Wrong tag here is the most common failure: the device shows a Funnel badge but the public DNS record is never published, so GitHub gets “failed to connect to host”.
Admin console → DNS: enable MagicDNS and HTTPS Certificates (two separate toggles; both required). Leave Override DNS servers off.
kubectl apply -k deploy/manifests/
kubectl get ingress -n opsgentic opsgentic-webhook -o wide # ADDRESS = public hostname
The public URL is https://<ingress-host>.<tailnet>.ts.net (e.g.
https://opsgentic-webhook.tail87cac3.ts.net).
dig @8.8.8.8 <host>.<tailnet>.ts.net A +short # must return an IP
curl -i https://<host>.<tailnet>.ts.net/healthz # must return 200 {"status":"ok"}
No public DNS after ~15 min → re-check the ACL funnel target (step 2), then
kubectl exec -n tailscale <proxy-pod> -- tailscale funnel reset and restart the proxy
statefulset.
In the GitHub App settings:
https://<host>.<tailnet>.ts.net/webhook/githubGITHUB_WEBHOOK_SECRET).application/json.Pull requests: Read & write and Issues: Read & write (PR
conversation comments use the issues comments API). Contents: Read & write is already
needed to open PRs.After saving, use Advanced → Recent Deliveries → Redeliver to send a test ping; a
healthy endpoint returns 204 for non-issue_comment events.
| Key | Where | Value |
|---|---|---|
GITHUB_WEBHOOK_SECRET |
opsgentic-secrets Secret |
must match the GitHub App webhook secret |
GITHUB_AGENT_HANDLE |
opsgentic-config ConfigMap |
trigger token / bot login (default opsgentic-agent) |
PR_RESPONDER_MAX_COMMENTS |
ConfigMap (optional) | conversation history depth (default 20) |
Both the API and worker Deployments load these via envFrom, so a rollout restart picks
them up:
kubectl rollout restart deploy/opsgentic deploy/opsgentic-worker -n opsgentic
The agent posts comments and commits with the GitHub App installation token (no extra
credential). The dedup table opsgentic_pr_events is created automatically.
curl https://<host>.<tailnet>.ts.net/healthz → 200 from outside the tailnet.@opsgentic-agent give me evidence.| Symptom | Cause | Fix |
|---|---|---|
dig from outside tailnet → NXDOMAIN / no A record |
Funnel DNS not published — ACL funnel attr on the wrong tag |
Target tag:k8s (proxy tag), not tag:k8s-operator; enable HTTPS Certificates |
| GitHub delivery: failed to connect to host | Public DNS/HTTPS not live | Fix the tunnel (above); the name must resolve from a non-tailnet machine |
| Delivery returns 401 | Secret mismatch | GITHUB_WEBHOOK_SECRET must equal the GitHub App webhook secret |
| Delivery returns 404 | Running image lacks the endpoint | Rebuild/push the opsgentic image with the current code |
| Delivery returns 204, no reply | Filtered out: not a PR comment, listen rule not satisfied, duplicate, or the agent’s own comment | Comment on a PR (not an issue); include @opsgentic-agent; check it is a new comment |
| 202 but no reply appears | Worker not running the new code / task failing | kubectl logs deploy/opsgentic-worker; ensure the worker is on the same image |
Can’t @mention the app in the UI |
A GitHub App is not @-mentionable | Expected — type @opsgentic-agent as literal text; it still triggers |
See USAGE.md for the alert→remediation flow and ARCHITECTURE.md for internals.