vigoo's software development blog

Golem 1.5 features - Part 2: Webhooks

Posted on April 10, 2026

Introduction

I am writing a series of short posts showcasing the new features of Golem 1.5, to be released at the end of April, 2026. The episodes of this series will be short and assume the reader knows what Golem is. Check my other Golem-related posts for more information!

Parts released so far:

Webhooks

We have seen how we can map our agents to HTTP APIs in the previous post. Another new feature of Golem 1.5, closely related to that, is the ability to create webhooks and await them.

Let's see how it works!

Creating a webhook

Webhooks are built on top of Golem Promises, which were available in previous Golem releases as well. These are entities you can create from code and then await - while the agent is waiting, it gets fully suspended, consuming no resources.

What's new is that we can now export these promises as webhook URLs that make it very easy to complete them from a third party system.

const webhook = createWebhook();
const url = webhook.getUrl();

// At this point we can somehow advertise this `url` - return as a result, post to a 3rd party API, etc

const payload = await webhook; // block until someone calls the webhook with a payload
const result: T = payload.json();
let webhook = create_webhook();
let url = webhook.url();

// At this point we can somehow advertise this `url` - return as a result, post to a 3rd party API, etc
 
let request = webhook.await;
let data: T = request.json().unwrap();
val webhook = HostApi.createWebhook()
val url = webhook.url

// At this point we can somehow advertise this `url` - return as a result, post to a 3rd party API, etc

webhook.await().map { payload =>
  val event = payload.json[T]()
  // ...
}
let webhook = @webhook.create()
let url = webhook.url()

// At this point we can somehow advertise this `url` - return as a result, post to a 3rd party API, etc

let payload = webhook.wait()
let text = payload.text()

Calling the webhook

The webhook URL simply awaits a POST request with an arbitrary body. This body is what the payload's helper methods are returning as raw byte array, string or parsed JSON.

Customizing the webhook URL

There are two ways to customize the webhook URL, which is having the following form:

https://<domain>/<prefix>/<suffix>/<id> 

The <domain> part is the domain where our API is deployed to. The <prefix> is /webhooks by default, and it can be customized in the deployment section of the Golem application manifest:

httpApi:
  deployments:
    default:
      - domain: example.com
        webhookUrl: "/my-custom-webhooks/"
        agents:
          # ...

The <suffix> part is the agent's type name in kebab-case by default, so for example my-workflow if our agent type is MyWorkflow. It can be customized by setting webhook suffix on our mount point:

@agent({
  mount: '/workflow/{id}',
  webhookSuffix: '/workflow-hooks'
})
class Workflow extends BaseAgent {    
  // ...
}
#[agent_definition(
    mount = "/workflow/{id}",
    webhook_suffix = "/workflow-hooks"
)]
pub trait Workflow {
    // ...
}
@agentDefinition(
  mount = "/workflow/{id}",
  webhookSuffix = "/workflow-hooks",
)
trait Workflow extends BaseAgent {
  // ...
}
#derive.agent
#derive.mount("/workflow/{id}")
#derive.mount_webhook_suffix("/workflow-hooks")
pub(all) struct Workflow {
  // ...
}