Automation
AgentDB can act when your data changes, or at a time you choose. With it you can:
- tell your own service about new or changed records, with a webhook;
- create a task every Monday morning, with a scheduled job;
- start onboarding when a contact becomes a customer, with a flow;
- let agents and people hand work to each other in channels and the inbox;
- book meetings in a calendar.
AgentDB stores the rules and runs them. It never runs an AI model itself. An action writes a record, sends a webhook or schedules another job. Your agent does the actual work.
The examples on this page use a small contact list and a task list:
{"tool": "schema_define_object", "arguments": {"name": "contact"}}{"tool": "schema_define_field", "arguments": {"object": "contact", "name": "name", "type": "text"}}{"tool": "schema_define_field", "arguments": {"object": "contact", "name": "stage", "type": "enum", "enum_values": ["lead", "customer"]}}{"tool": "schema_define_object", "arguments": {"name": "task"}}{"tool": "schema_define_field", "arguments": {"object": "task", "name": "title", "type": "text"}}#Webhooks
A webhook sends an HTTPS POST to your endpoint when something happens. You choose the events, and optionally the objects.
{"tool": "webhooks_create", "arguments": {"name": "Contact changes", "url": "https://hooks.example.com/agentdb", "events": ["record.created", "record.updated"], "objects": ["contact"]}}- The secret is shown once. It starts with
whsec_. Store it on your server.webhooks_rotate_secretgives a new one. - Events include record, relationship, schema, file, message, inbox and approval events.
"*"means all. - Payloads carry ids, not values. Your service fetches the record with its own key.
- Private addresses are refused. The URL must be public HTTPS.
- Test it:
webhooks_testsends a signed test delivery.
#Verify the signature
Every request carries X-AgentDB-Signature: t=<unix time>,v1=<signature>. The signature is an HMAC-SHA256 of <t>.<raw body>, keyed with your secret. Reject requests older than 5 minutes.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret, header, rawBody, toleranceSeconds = 300) {
const parts = Object.groupBy(header.split(","), (p) => p.slice(0, p.indexOf("=")));
const t = Number(parts.t?.[0]?.slice(2));
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
return (parts.v1 ?? []).some((v) => {
const got = Buffer.from(v.slice(3), "hex");
return got.length === expected.length && timingSafeEqual(got, expected);
});
}During a secret rotation, the header holds two v1 values. The code above accepts either one.
#Delivery
- At least once. The same event can arrive twice. Remove duplicates with the
X-AgentDB-Event-Idheader. - In order. Each webhook gets events in the order they happened.
- Retries: AgentDB retries a failed delivery 10 times over about 2.4 hours. Any 2xx answer counts as success.
- Log:
webhooks_deliveriesshows each attempt.webhooks_redeliversends a failed delivery again.
Only owners and admins manage webhooks.
#Scheduled jobs
A job runs an action at a set time. There are three kinds of schedule:
| Schedule | Example |
|---|---|
| Once | {"type": "once", "at": "2027-01-15T09:00:00Z"} |
| Cron | {"type": "cron", "expression": "0 9 * * 1-5", "timezone": "Europe/London"} |
| Repeat rule (RRULE) | {"type": "rrule", "rule": "FREQ=MONTHLY;BYDAY=-1FR", "start": "2027-01-01T10:00", "timezone": "Europe/London"} |
Check a schedule before you save it. schedule_preview lists the next times and creates nothing.
{"tool": "schedule_preview", "arguments": {"schedule": {"type": "rrule", "rule": "FREQ=MONTHLY;BYDAY=-1FR", "start": "2027-01-01T10:00", "timezone": "Europe/London"}, "count": 3}}This job creates a task every Monday at 09:00, London time:
{"tool": "jobs_create", "arguments": {"name": "Weekly digest", "schedule": {"type": "cron", "expression": "0 9 * * 1", "timezone": "Europe/London"}, "action": {"type": "create_record", "object": "task", "data": {"title": "Write the weekly digest"}}}}Actions:
create_record: for example a task record your agent checks.update_record: change one record.webhook: send a signed delivery to one of your webhooks.run_flow: run a flow, for example over many records.
What AgentDB guarantees:
- Each time runs once. A record action takes effect exactly once, also after a restart.
- Retries: a failed action is retried, up to 5 times by default.
jobs_retry_runtries a failed run again. - Missed times: after downtime,
misseddecides. The defaultrun_onceruns only the latest missed time. - Time zones use IANA names, such as
Europe/London. Daylight saving changes are handled. - Pause:
jobs_updatewithstatus: "paused". Resume withstatus: "active".
#Flows
A flow is a rule: "when this happens, do that". It reacts to records being created, updated or deleted, or to a field changing.
{"tool": "flows_create", "arguments": {
"name": "New customer -> onboarding task",
"trigger": {"type": "field.changed", "object": "contact", "fields": ["stage"]},
"where": {"all": [{"field": "stage", "op": "eq", "value": "customer"}]},
"actions": [{"type": "create_record", "object": "task", "data": {"title": "Onboard {{record.data.name}}"}}]
}}Values such as {{record.data.name}}, {{record.id}} or {{today+30d}} are filled in when the flow runs.
Actions:
set_fieldchanges the record that started the flow.create_recordanddelete_recordadd or remove records.notifyputs an item in someone's inbox.webhooksends a signed delivery.scheduleruns an action later, for example after a week.proposeasks a person for approval first. See Approvals and the AgentHub.
Test a flow on a real record. flows_test runs the actions and then rolls them back. Nothing is written or sent.
{"tool": "records_create", "arguments": {"object": "contact", "data": {"name": "Ada Lovelace", "stage": "customer"}}}{"tool": "flows_test", "arguments": {"flow_id": "$FLOW_ID", "record_id": "$CONTACT_ID", "event": "record.updated", "fields": ["stage"]}}A flow ignores its own writes. Chains of flows stop after 3 steps by default, so flows cannot loop forever.
#Channels and messages
A channel holds work messages between agents and people. Messages stay until you remove them or the channel's retention ends.
{"tool": "channels_create", "arguments": {"name": "sales", "topic": "Deals and handoffs"}}{"tool": "messages_post", "arguments": {"channel_id": "$CHANNEL_ID", "body": "Example Ltd signed. Please start onboarding.", "priority": "high"}}- Public channels are readable by everyone in the workspace. Private channels are visible to members only.
- A message is Markdown. It can also carry a structured
payload, such as a task handoff. - Mentions such as
@agent:agt_...put an item in that agent's inbox. - Every message gets a sequence number. An agent reads new messages with
channels_pendingand confirms them withchannels_ack. dedupe_keymakes a post safe to repeat.
#Inbox
Each agent, member and key has an inbox. It collects mentions, direct messages, assignments and notifications.
{"tool": "workspace_info", "arguments": {}}{"tool": "inbox_notify", "arguments": {"recipient": "$ME", "title": "Contract from Example Ltd arrived", "text": "Please review it today."}}{"tool": "inbox_list", "arguments": {}}inbox_update marks items as read or done. People see their inbox in the AgentHub. The inbox is experimental and may change before version 2.0.
#Calendar
Calendars book time for people, agents and resources, such as a meeting room.
{"tool": "calendars_create", "arguments": {"name": "Team", "timezone": "Europe/London"}}{"tool": "events_create", "arguments": {"calendar_id": "$CALENDAR_ID", "title": "Kick-off with Example Ltd", "start": "2027-01-12T10:00", "duration_minutes": 60}}calendar_find_slotsfinds a free time for several calendars and people. It books nothing.recurrencetakes a repeat rule, such asFREQ=WEEKLY;BYDAY=MO.reminderssendcalendar.reminderevents before the event starts.calendar_export_icsandcalendar_import_icsexchange events with other calendar apps.