Skip to main content
Webhooks let external services trigger ollim-bot background forks over HTTP. A CI pipeline can notify the bot about a failed build, a monitoring tool can report downtime, or any service that speaks HTTP can send structured data for the agent to act on. Webhook specs are markdown files with YAML frontmatter — the same format as routines and reminders. The agent can create and manage them conversationally through file access.

Prerequisites

  • ollim-bot running (quickstart)
  • Two environment variables set in .env:
VariableRequiredDefaultDescription
WEBHOOK_PORTYesPort for the HTTP server (e.g. 8420)
WEBHOOK_SECRETYesSecret token for authenticating requests
If WEBHOOK_PORT is set but WEBHOOK_SECRET is missing, the server refuses to start.

Setup

1

Set environment variables

Add both variables to your .env file:
WEBHOOK_PORT=8420
WEBHOOK_SECRET=my-webhook-secret-token
2

Create the webhooks directory

mkdir -p ~/.ollim-bot/webhooks
3

Write a webhook spec

Create a markdown file in ~/.ollim-bot/webhooks/. The filename is arbitrary — the id field in the frontmatter determines the URL path.
~/.ollim-bot/webhooks/github-ci.md
---
id: github-ci
isolated: true
model: haiku
allow-ping: true
update-main-session: on_ping
skills:
  - "repo-status"
fields:
  type: object
  required: [repo, status]
  properties:
    repo:
      type: string
      maxLength: 200
    branch:
      type: string
      maxLength: 200
    status:
      type: string
      enum: [success, failure, cancelled]
    url:
      type: string
      format: uri
      maxLength: 500
  additionalProperties: false
---
GitHub Actions CI result:
- Repository: {repo}
- Branch: {branch}
- Status: {status}
- URL: {url}

Check the build status and decide whether this warrants
my attention.
4

Restart the bot

The webhook server starts automatically when the bot launches. You’ll see in the logs:
Webhook server started on 127.0.0.1:8420
5

Send a test request

curl -X POST http://127.0.0.1:8420/hook/github-ci \
  -H "Authorization: Bearer my-webhook-secret-token" \
  -H "Content-Type: application/json" \
  -d '{"repo": "ollim-bot", "branch": "main",
       "status": "failure",
       "url": "https://github.com/Ollim-AI/ollim-bot/actions/runs/123"}'
A successful request returns 202 Accepted with {"status": "accepted"}.

Spec file format

Each webhook spec is a .md file in ~/.ollim-bot/webhooks/ with YAML frontmatter and a markdown body.

Frontmatter fields

FieldTypeDefaultDescription
idstringURL path — requests go to /hook/{id}
fieldsobjectValidation rules for the payload (JSON Schema)
isolatedboolfalseRun the fork in isolated mode
modelstringnullOverride the model (e.g. haiku)
thinkingbooltrueEnable extended thinking
allow-pingbooltrueAllow the fork to ping the user
update-main-sessionstringon_pingWhen to write back to main session
skillslist[string] | nullnullSkill names to load at fire time
subagentstring | nullnullSubagent to delegate the core task to
The isolated, model, thinking, allow-ping, and update-main-session fields have the same semantics as background fork configuration.

Markdown body

The body is a prompt template — instructions for what the agent should do with the incoming data. The validated JSON payload is passed to the agent separately (as a fenced data block in the prompt), so you don’t need placeholders. Just describe the task and reference field names naturally.

Fields schema

The fields value is a set of validation rules using JSON Schema. It defines which fields the webhook accepts, their types, and any constraints.
  • Use enum over free string wherever values are known
  • Use integer / boolean over string for non-text data
  • Always set maxLength on string fields (default 500 if omitted)
  • Always set additionalProperties: false

How requests are processed

When an HTTP request hits /hook/{id}, the bot authenticates it, validates the payload against the spec’s field rules, and fires a background fork with the validated data. The caller receives 202 Accepted immediately — the bot processes the webhook asynchronously. Invalid requests are rejected with descriptive errors:
ConditionStatusResponse body
Bad or missing Bearer token401{"error": "unauthorized"}
Unknown webhook path404{"error": "webhook not found: <slug>"}
Invalid JSON body400{"error": "invalid json"}
Schema validation failure400{"error": "validation failed", "details": [...]}
  1. Auth check — verifies the secret token in the request header.
  2. Spec lookup — matches the URL path to a spec’s id field.
  3. JSON parse — reads the request body as JSON.
  4. Schema validation — validates the payload against the spec’s fields rules.
  5. Prompt construction — the bot builds a prompt combining the task instructions (markdown body) with the validated JSON payload as a fenced data block, keeping webhook data clearly separated from instructions.
  6. 202 Accepted — response sent immediately.
  7. Subagent validation — if the spec references a subagent, the bot verifies it exists. Unknown subagents skip dispatch entirely.
  8. Injection screening — free-form text fields are checked for attempts to trick the bot (30-second timeout — if screening fails, the webhook proceeds). Flagged payloads are skipped and logged.
  9. Skill validation — if the spec references skills, the bot verifies each one exists in ~/.ollim-bot/skills/. Missing skills skip dispatch entirely.
  10. Dispatch — a background fork runs with the spec’s configuration.
Webhooks accept external input, so four layers of defense prevent outside data from tricking the bot:
LayerWhat it catches
Schema validationWrong types, undeclared fields, oversized strings
Data labelingWebhook data is clearly separated from bot instructions
Injection screeningFree-form text checked for attempts to trick the bot
Size limits10 KB payload cap, 500-character strings, 20 properties max
If the injection screening check itself fails (e.g. a network error), the webhook is processed normally rather than blocked. This prevents screening outages from blocking legitimate webhooks.

Troubleshooting

Check that both WEBHOOK_PORT and WEBHOOK_SECRET are set in your .env file. If only WEBHOOK_PORT is set, the server logs an error and stays disabled.
Verify your Authorization header matches Bearer <WEBHOOK_SECRET> exactly.
Specs are re-read each time a request arrives, so changes take effect immediately without restarting. Verify the file exists in ~/.ollim-bot/webhooks/ and that the id field in the frontmatter matches the path in your URL.
Several things can cause a webhook to be accepted (202) but produce no action:
  • Injection screening flagged a field value. Look for Webhook <slug>: flagged fields [...], skipping dispatch in the logs.
  • Missing skills — the spec references a skill that doesn’t exist in ~/.ollim-bot/skills/. Look for Webhook <slug>: unknown skills [...], skipping.
  • Missing subagent — the spec references a subagent that doesn’t exist. Look for Webhook <slug>: unknown subagent '...', skipping.

Next steps

Background forks

How background forks work — the execution model webhooks use.

Ping budget

How the ping budget controls when forks can notify you.

Google integration

Connect Google services for tasks, calendar, and email access.

Discord tools

The tools available to the agent during webhook-triggered forks.