golemcloud/golem/golem-add-webhook-go

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Receiving external webhook callbacks in a Go Golem agent. Use when the user asks to create webhooks, receive webhook callbacks, integrate with webhook-driven external APIs, or generate temporary callback URLs for external services in a Go Golem project.

Install

npx vskill@latest install golemcloud/golem/golem-add-webhook-go

SKILL.md

Using Webhooks in a Go Golem Agent

Overview

A Golem webhook lets an agent mint a temporary public URL that an external system POSTs to; the POST body is delivered back to the agent. Under the hood a webhook is a Golem promise. Creation does not suspend the agent. A durable agent awaiting the callback can suspend after the suspension policy delay, freeing guest execution resources while persisted state and other resources remain. The wait survives restarts via oplog replay.

A webhook is a promise completed by an HTTP POST:

  • golem.NewWebhook[T]() creates the promise and the URL that completes it; w.URL() is the URL to hand out.
  • w.ID() returns the golem.PromiseID to persist in agent state.
  • golem.PromiseByID[T](id).MustAwait() (or w.MustAwait()) suspends until the POST arrives and returns the body decoded as T; Await() returns (T, error) instead.

This is useful for payment gateways, CI/CD, GitHub/Stripe callbacks, and any event-driven workflow where an external system notifies the agent.

Prerequisites

The agent type must have an HTTP mount (Spec.HTTP = &golem.Mount{Path: "/..."}) and be deployed via an httpApi deployment in golem.yaml. Without that, NewWebhook traps (it is fail-loud). The mount does not need any HTTP endpoints — it only makes the agent HTTP-API-deployable.

Steps

  1. Add an HTTP mount to the agent's Spec (see golem-add-http-endpoint-go).
  2. Create a webhook; persist its PromiseID in state and return/share the URL.
  3. Await the callback in a later invocation via the stored id.
  4. Deploy behind an httpApi so the URL is reachable.

API

Function / methodDescription
golem.NewWebhook[T]()Create a promise and the public URL that a POST completes; returns *golem.Webhook[T] (a *golem.Promise[T] plus URL()); requires the agent be HTTP-API-deployed
(*Promise[T]).WebhookURL() stringMint the URL for a promise created with golem.NewPromise[T]()
(*Promise[T]).ID() golem.PromiseIDThe durable id — persist it to await/complete in a later invocation
(*Promise[T]).Await() (T, error)Suspend until completed; returns the POST body decoded as T (JSON, or raw bytes when T is []byte), or an error if it does not decode
(*Promise[T]).MustAwait() TAwait that panics if the body does not decode
golem.PromiseByID[T](id)Rebuild a handle from a stored PromiseID
golem.CompletePromise[T](id, value)Complete a promise from another agent (external completers use the URL instead)

Complete example

Definition (agents/webhookdemo/webhookdemo.go)
go
// Package webhookdemo is the DEFINITION of a webhook agent. It needs the HTTP
// mount below (plus an httpApi deployment) or NewWebhook traps.
package webhookdemo
import "github.com/golemcloud/golem/sdks/go/golem"
type ID struct{ Queue string } // bound by {queue} in the mount path
// Event is the webhook payload — JSON tags are the contract for the caller's POST.
type Event struct {
OrderID string `json:"orderId"`
Amount int64 `json:"amount"`
}
var Agent = golem.DefineAgent[ID](golem.Spec{
Name: "WebhookDemoAgent",
Description: "Completes a promise from an external webhook POST",
HTTP: &golem.Mount{Path: "/hooks/{queue}"}, // makes the agent HTTP-API-deployable
})
var (
Open = Agent.Method[golem.Unit, string]("open", golem.Description("Create a promise and return its webhook URL"))
Result = Agent.Method[golem.Unit, Event]("result", golem.Description("Await the payload POSTed to the webhook URL"))
)
Implementation (agents/webhookdemo/impl/impl.go)
go
package impl
import (
"myapp/agents/webhookdemo"
"github.com/golemcloud/golem/sdks/go/golem"
)
type state struct {
pending golem.PromiseID
open bool
}
var agent = webhookdemo.Agent.Implement(func(webhookdemo.ID) *state { return &state{} })
func init() {
// Mint a URL; persist the PromiseID so a later invocation can await it.
agent.Handle(webhookdemo.Open, func(ctx *golem.Context[state], _ golem.Unit) string {
w := golem.NewWebhook[webhookdemo.Event]()
ctx.State.pending = w.ID()
ctx.State.open = true
return w.URL() // hand this URL to the external system
})
// Suspend until the external POST arrives; returns the decoded body.
agent.Handle(webhookdemo.Result, func(ctx *golem.Context[state], _ golem.Unit) webhookdemo.Event {
if !ctx.State.open {
panic("no open webhook — call open first")
}
return golem.PromiseByID[webhookdemo.Event](ctx.State.pending).MustAwait()
})
}

Payload decoding

Await() decodes the POST body as its type parameter T via JSON, and returns an error when the body does not decode. Use a struct with json tags (as Event above) for structured payloads, or golem.PromiseByID[[]byte](id).Await() to receive the raw request bytes unchanged.

Webhook URL structure and suffix

The minted URL has the shape https://<domain>/<prefix>/<suffix>/<id>:

  • <domain> — where the HTTP API is deployed.
  • <prefix> — defaults to /webhooks, customizable via webhookUrl in the httpApi deployment section of golem.yaml.
  • <suffix> — defaults to the agent type name in kebab-case; override it with Mount.WebhookSuffix.
  • <id> — a unique per-webhook identifier.
go
HTTP: &golem.Mount{Path: "/api/orders/{id}", WebhookSuffix: "/workflow-hooks"},

Key Constraints

  • The agent must set Spec.HTTP and be deployed via httpApi, or WebhookURL() panics, which traps the component, as in Rust.
  • Only the agent that created the promise may Await it; awaiting from another agent traps in the host.
  • Only a POST to the URL completes the promise. Completion is first-write-wins: duplicate POSTs return HTTP 204 without replacing the first payload. Completion does not immediately invalidate the URL, and a later Await returns the recorded body from the oplog.
  • A durable agent can suspend after the suspension policy delay while awaiting — it survives failures, restarts, and updates.
  • Go difference from Rust: Mount.WebhookSuffix must be literal segments only — path variables like {agent-type} or {name} in the suffix are rejected in the Go SDK. Rust supports system variables such as {agent-type} and {agent-version}, not constructor parameters such as {name}.
Related Skills
SkillWhen to Load
golem-add-http-endpoint-goSet up the HTTP mount + httpApi deployment webhooks require
golem-add-agent-goDefine the agent and its payload types
golem-add-http-auth-goRequire authentication on the agent's other endpoints

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
1,514
Repository forks
210
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/golemcloud/golem/golem-add-webhook-go/badge)](https://verified-skill.com/skills/golemcloud/golem/golem-add-webhook-go)

Something wrong with this skill or its page? Tell us.