GC
Cookbook / Monitor CI with WebhooksMenu
6 min read·Updated 2026-04-10

Monitor CI with Webhooks

Custom webhook hook turns CI failure payloads into agent prompts. Verified with curl, then wired to GitHub Actions.

What you will build

This recipe connects a CI pipeline to the runtime through a custom webhook hook. When a build fails, the CI system POSTs a JSON payload to the runtime; the hook renders a Mustache template against the payload, launches a session with the review skill active, and the agent investigates.

You should already understand the webhook lifecycle and delivery states from Webhooks. This recipe does not re-explain them.

Prerequisites

  • GolemCore Bot is running on a host reachable from your CI system. For local experiments, ngrok or a tailnet is enough.
  • Webhooks are enabled in preferences/webhooks.json ("enabled": true).
  • A shared secret is set. Any CI sender must include it in the Authorization header.
  • A skill named ci-triage (or similar) exists. It can be a minimal stub for now — the review skill from the scheduled-code-review recipe is a good starting point.

1. Define the custom hook

Hooks live under webhooks.hooks in the preferences file. Each hook has a path, a Mustache template that renders the payload into the initial agent prompt, and optionally a skill to activate for the session.

preferences/webhooks.json
json
{
  "enabled": true,
  "secret": "change-me-before-production",
  "hooks": {
    "ci-failure": {
      "name": "ci-failure",
      "path": "/api/hooks/ci-failure",
      "active": true,
      "skill": "ci-triage",
      "messageTemplate": "CI build failed on branch {{branch}}.\nCommit: {{commit}}\nSummary: {{summary}}\nLogs: {{log_url}}\n\nInvestigate the failure and propose a fix."
    }
  }
}
Reload or restart to pick up the change
bash
docker exec golemcore-bot curl -s -X POST http://localhost:8080/api/admin/reload-webhooks
Example output
text
{"ok":true,"hooks":["ci-failure"]}

2. Send a test payload

Before touching your CI config, simulate the payload with curl. This isolates template rendering and authentication from the CI plumbing.

Simulate a CI failure payload
bash
curl -sS -X POST http://localhost:8080/api/hooks/ci-failure \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer change-me-before-production" \
  -d '{
    "branch": "main",
    "commit": "9f3a1c2",
    "summary": "3 of 412 tests failing in PaymentServiceTest",
    "log_url": "https://ci.example.com/builds/1234"
  }'
Example response
json
{
  "delivery_id": "wh_01HZ7K3V2Q",
  "state": "DELIVERED",
  "session_id": "sess_2026-04-10_091422"
}

The session is created immediately; the agent starts working on the rendered prompt in the background. Check Sessions to see the turn unfold.

3. Wire the CI system

Once the local curl works, configure your CI provider to call the same endpoint on failure. The exact shape depends on the provider; the pattern is always the same.

GitHub Actions workflow snippet
yaml
jobs:
  tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./scripts/test.sh
      - name: Notify GolemCore on failure
        if: failure()
        run: |
          curl -sS -X POST ${{ secrets.GOLEMCORE_WEBHOOK_URL }} \
            -H "Content-Type: application/json" \
            -H "Authorization: Bearer ${{ secrets.GOLEMCORE_WEBHOOK_SECRET }}" \
            -d @- <<'EOF'
          {
            "branch": "${{ github.ref_name }}",
            "commit": "${{ github.sha }}",
            "summary": "Test job failed in ${{ github.workflow }}",
            "log_url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
          }
          EOF

Trigger a failing build intentionally. Within a few seconds a new session should appear in the dashboard with the rendered prompt as its first turn.

Variants

No skill, just a prompt

Drop the skill field. The session starts without any overlay and the agent uses default tools only — useful when different CI systems need different follow-ups.

Lightweight

Separate success and failure hooks

Add a second hook at /api/hooks/ci-success that only runs on deployments. Use a different messageTemplate to signal 'verify the deploy went live' instead of 'investigate the failure'.

Multi-hook

Feed an Auto Mode goal

Route the hook to an Auto Mode goal instead of a one-shot session by setting goal instead of skill. Builds that fail repeatedly accumulate into the same diary.

Accumulate

Custom signature verification

Proxy through an HMAC-verifying gateway (Cloudflare Worker, nginx) if the CI provider signs payloads differently. The runtime only checks the Bearer secret — put any extra verification in front.

Security

Gotchas

401 Unauthorized

Check: curl response body. A 401 means the Authorization header is missing or the secret does not match preferences/webhooks.json. Fix: re-check the secret value and the Bearer prefix.

auth

Delivery stuck in PENDING

Check: the delivery state in Dashboard → Webhooks. If it is PENDING for more than a few seconds, the runtime is under load or the hook session could not start. Fix: inspect the Sessions page for a stuck session and the logs for skill activation errors.

delivery

Placeholders not substituted

Check: the rendered prompt in the Session first turn. If it contains literal {{branch}} instead of the value, the payload field name does not match the template. Fix: align the curl/CI payload fields with the Mustache placeholders exactly.

template

404 on the hook URL

Check: docker logs for 'hook not found'. Fix: the path in the hook definition must exactly match the URL the sender hits. The path is case-sensitive and includes the /api/hooks/ prefix.

routing

What to do next