Terminology that trips teams: CodeBuild’s console “webhook” usually means Git → CodeBuild inside AWS. To reach an external HTTPS endpoint when a build ends, the minimal managed pattern is Amazon EventBridge on the default bus with detail-type CodeBuild Build State Change, targeting an API destination (webhook-style HTTPS). This article uses that pattern and treats the POST as your “CodeBuild completion webhook” toward OpenClaw.
| Mechanism | Direction | Fits this guide? |
|---|---|---|
| CodeBuild source webhook | Git provider → starts build in AWS | No—never hits your Mac |
| EventBridge + API destination | AWS → HTTPS you control | Yes—minimal outbound “webhook” |
| Lambda → custom URL | AWS → your code → Mac | Yes—more logic, same TLS rules |
- Five-second ceiling: API destination invocations expect a quick HTTP 2xx; long
npm ciruns must move to a background worker on the Mac. - Silent 401: Connection header templates drift from what your Node handler reads (
Authorizationcasing, missingBearerprefix). - Wrong Region: the rule on
us-east-1never sees builds emitted inus-west-2.
Install, Node 22+, and openclaw onboard --install-daemon
Current OpenClaw releases expect a modern Node runtime—treat Node.js 22 LTS as the baseline on the Apple Silicon user that owns the gateway. Install the CLI (npm install -g openclaw@latest), then run openclaw onboard --install-daemon so the wizard finishes model/workspace prompts and registers the LaunchAgent described in upstream docs (logged-in session; headless hosts may need a custom LaunchDaemon). Re-run openclaw doctor until PATH, credentials, and legacy keys are clean; complete openclaw health (the wizard’s health step wraps this) before you expose any public URL.
Persist the same NODE_BINARY and PATH inside the plist EnvironmentVariables block as you use over SSH—drift here is the primary reason “it worked in Terminal but not from launchd.” If you pre-set OPENCLAW_GATEWAY_TOKEN before onboarding, recent upstream fixes ensure the wizard respects it instead of generating a mismatched random token for WebSocket clients.
Gateway port & health: onboarding prompts for bind mode, auth, and gateway port (stored under gateway.* in ~/.openclaw/openclaw.json). Tutorials often cite 18789 for the local control UI—verify your file rather than assuming. After install, use openclaw health and openclaw status --deep to confirm the process answers probes; for infra monitors, add an HTTPS health check against your reverse-proxy path that returns 200 only when the gateway child is reachable on loopback.
AWS: EventBridge rule + API destination
Create an EventBridge connection with API key authorization: map the API key to Authorization header value Bearer <long-secret>. Store the same secret on the Mac in ~/.config/openclaw/aws-codebuild-hook.secret with mode 600. Next create an API destination with endpoint https://hooks.example.com/openclaw/codebuild, HTTP method POST, and invocation rate limits per AWS guidance.
Add a rule on the default event bus: source aws.codebuild, detail-type CodeBuild Build State Change, and detail match on terminal states such as SUCCEEDED, FAILED, FAULT, and STOPPED so you do not preflight every IN_PROGRESS noise event. Scope with detail.project-name or ARN prefix matching only the repositories you own. Attach the API destination as the target; optionally apply an input transformer that forwards detail.build-id, detail.build-status, detail.project-name, detail.additional-information, plus account and Region for deep links.
- Minimal IAM footprint: grant operators
events:PutRule,events:PutTargets,events:DescribeRule, andevents:ListTargetsByRuleon the bus ARN; secrets live in the EventBridge connection, not in the rule JSON. - Log fields to print on one line: EventBridge
id,time,region,account,detail.build-id,detail.build-status,detail.project-name, and your correlation token. - Retry story: EventBridge retries failed API destination deliveries for hours; your Mac should still treat summaries idempotently and use outbound 2s / 4s / 8s sleeps when POSTing to chat vendors.
# Example event pattern (pseudo-YAML) — tighten project-name to your own
{
"source": ["aws.codebuild"],
"detail-type": ["CodeBuild Build State Change"],
"detail": {
"build-status": ["SUCCEEDED", "FAILED", "FAULT", "STOPPED"],
"project-name": ["your-ci-project"]
}
}
Gateway path, bearer token, and TLS
Bind the automation HTTP server to 127.0.0.1 and terminate TLS on nginx or Caddy at the edge. Verify curl -v https://hooks.example.com/openclaw/codebuild from the public internet uses the same certificate chain AWS will validate. Your handler should read the raw body (even if today you only check a bearer) so you can add HMAC later without redeploying the proxy.
Compare with the CircleCI recipe in OpenClaw + CircleCI webhook lockfile summary—swap signature headers for static bearer auth, keep the same “fast 200 + async worker” skeleton.
// Minimal Node guard (conceptual)
const secret = fs.readFileSync(process.env.HOOK_SECRET_FILE, 'utf8').trim();
const hdr = req.headers.authorization || '';
if (hdr !== `Bearer ${secret}`) return res.status(401).end();
res.status(200).json({ ok: true, buildId: body.detail?.['build-id'] });
// enqueue preflight job here — do not await npm ci in this function
Webhook validation checklist
curl -H "Authorization: Bearer …" against localhost through SSH port-forward to confirm parsing before AWS traffic hits you.build-id.id redelivers.Dependency preflight + summary POST
Map detail.source-version or CodeBuild environment variables you control to a git ref, clone shallow into /var/tmp/codebuild-openclaw/<build-id>, then run stack-specific dry runs (npm ci --dry-run, pnpm install --frozen-lockfile --prefer-offline where supported, composer validate, bundle check). Capture the last eighty lines for the summary payload. The synchronous path should only verify auth, validate JSON shape, enqueue work, and return JSON with the build id.
When preflight completes, POST JSON to Slack/Teams or your internal API with projectName, buildId, status, preflightExitCode, log excerpt, and a console deep link. Use three outbound attempts with 2s / 4s / 8s sleeps and ~25s client timeout per attempt. For lockfile-only gates, mirror the shallow-clone plus manifest diff pattern from other OpenClaw CI articles—only the inbound trigger transport changes.
FAQ: “We never receive events”
Builds might publish to a different account (cross-account) or Region. Confirm the CodeBuild project ARN in the event sample matches the bus you edited; loosen the project-name predicate temporarily to validate flow.
Open the failed invocation in CloudWatch; 403/401 indicates header auth mismatch. 404 means the API destination URL path typo. TLS errors usually mean incomplete chain or SNI hostname mismatch.
EventBridge retries on non-2xx responses. Always return 200 after enqueue when auth passes, dedupe on detail.build-id + EventBridge id.
Ensure the gateway user has a logged-in GUI session for stock LaunchAgents, or migrate to a LaunchDaemon pattern documented for headless hosts. Compare environment blocks with a working SSH session.
Closing checklist
- Node 22+,
openclaw onboard --install-daemon,doctor+healthclean. - TLS → loopback; bearer secret on disk mode
600; handler under ~5s. - EventBridge rule on terminal statuses only; API destination Connection tested with curl.
- Preflight in worker; summaries with 2/4/8s outbound retries.
Laptops sleep; dedicated remote Mac capacity keeps EventBridge deliveries and OpenClaw workers online 24/7. Use MacPull Pricing and Purchase flows to add cores or RAM when preflight queues grow—the gradient CTA below links Help, a regional purchase page, and the blog index.
MacPull rents Apple Silicon hosts engineered for always-on CI glue: stable egress, datacenter power, and room to add more build agents when OpenClaw workloads expand.
Scale OpenClaw + AWS CodeBuild glue on a dedicated Mac
Help, purchase, and more OpenClaw tutorials—no login required to read.