Skip to content
GitHub Get Started
Orchestration

Webhooks

Use a lightweight HTTP server to receive webhooks and drive an agent. This example uses Hono to receive Slack webhooks and call an agent directly.

server.ts
import { agentOS, setup } from "@rivet-dev/agentos";
import { createClient } from "@rivet-dev/agentos/client";
import { Hono } from "hono";
import pi from "@agentos-software/pi";
const vm = agentOS({
software: [pi],
additionalInstructions: "You answer Slack messages concisely.",
});
export const registry = setup({ use: { vm } });
registry.start();
// Hono server to receive Slack webhooks
const app = new Hono();
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
app.post("/slack/events", async (c) => {
const body = await c.req.json();
// Handle Slack URL verification
if (body.type === "url_verification") {
return c.json({ challenge: body.challenge });
}
// Call the agent directly for a user message
if (body.event?.type === "message" && !body.event?.bot_id) {
const { channel, text, user } = body.event;
const agent = client.vm.getOrCreate("slack-agent");
const session = await agent.createSession("pi", {
env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
});
const result = await agent.sendPrompt(
session.sessionId,
`Slack message from ${user} in #${channel}:\n\n${text}\n\nRespond helpfully.`,
);
await agent.closeSession(session.sessionId);
// Post the response back to Slack
await fetch("https://slack.com/api/chat.postMessage", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}`,
},
body: JSON.stringify({ channel, text: result.text }),
});
}
return c.json({ ok: true });
});
export default app;

See Full Example

  1. Slack sends an HTTP POST to /slack/events
  2. The Hono handler validates the event and pushes it to the actor’s queue
  3. The queue processes messages one at a time, creating agent sessions for each
  4. The agent responds and the worker posts the reply back to Slack

The queue provides backpressure and durability. If the agent is busy, messages wait in the queue. If the server restarts, queued messages are replayed.

  • Return 200 from the webhook handler immediately after queuing. External services like Slack have short timeout windows.
  • Store webhook secrets in environment variables, not in code.