Add a webhook or a schedule
const url = 'https://api.asklucy.eu/v1/agents/example/triggers';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"type":"webhook","cron":"example","timezone":"example","callback_url":"https://example.com","input":"example","enabled":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.asklucy.eu/v1/agents/example/triggers \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "type": "webhook", "cron": "example", "timezone": "example", "callback_url": "https://example.com", "input": "example", "enabled": true }'Every trigger has a token (secret, lwh_…). A webhook’s
webhook_url carries it: POSTing to that URL starts a run
(receiveAgentWebhook). Lucy signs the trigger’s callbacks with it
(Lucy-Signature). The agent’s managers can copy the URL again
later (listAgentTriggers). At most 10 triggers per agent.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Header Parameters
Section titled “Header Parameters”Any unique string (a UUID works). Retries with the same key return the first result.
Request Bodyrequired
Section titled “Request Bodyrequired”object
Required for schedules.
Required for schedules.
At most 16 KB of JSON.
Callbacks
Section titled “Callbacks”runFinished
Section titled “runFinished”See AgentCallback.
Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>" keyed with the trigger's token>.
Request Bodyrequired
Section titled “Request Bodyrequired”What Lucy POSTs to a trigger’s callback_url when a run it started
ends (not for skipped runs). The request carries
Lucy-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>", keyed with the trigger's token> (the secret,
the last segment of a webhook’s URL): check it, and refuse a t
more than 5 minutes old. Lucy retries anything but a
2xx, with backoff, for 24 hours; the same run_id can arrive more
than once. Callbacks only go to https URLs that resolve to public
addresses.
object
queued waits for the agent’s run in progress; skipped: a
schedule fired while a run was still going, so this time didn’t
run.
object
object
A signed download link, valid 24 hours.
object
object
Tool calls.
Responses
Section titled “Responses”Received. Anything else is retried, with backoff, for 24 hours.
Refused; retried like any other failure.
Responses
Section titled “Responses”Created
object
Webhooks: where to POST (receiveAgentWebhook). The URL carries
the trigger’s token: it is a credential, like a Slack incoming
webhook’s. Only the agent’s managers see triggers (its owner,
or org_admins for a service agent), and they can copy it at any
time. Null for schedules.
Schedules: 5 fields (minute hour day-of-month month day-of-week), at most once every 15 minutes.
Schedules: the IANA time zone the cron is read in.
Schedules: the next time it fires; null while it or its agent is disabled. After an outage a schedule fires once, not once per missed time.
Where Lucy POSTs each run’s result when it ends (see AgentCallback). https only, to a public address.
Fixed input given to every run it starts (any JSON), next to a webhook’s payload. Null for none.
The token’s prefix and last 4 characters, to tell tokens apart.
After a rotation, until when the previous token (the previous URL) still works.
The trigger’s token, the last segment of a webhook’s webhook_url. It is the key of its callbacks’ Lucy-Signature. Lucy keeps it sealed; the agent’s managers see it again in webhook_url.
Example
{ "id": "trg_7Lp2WqZs9XcVb4Nm1KjH", "type": "webhook", "webhook_url": "https://api.asklucy.eu/v1/hooks/trg_7Lp2WqZs9XcVb4Nm1KjH/lwh_5mKq0Zp3Xw8Rt2Lv6Nb9Hc1Jd4Fg7Sa0Ye3Ui6Ok", "cron": "0 7 * * 1-5", "timezone": "Europe/Luxembourg", "secret_hint": "lwh_…x9Qa", "created_by": { "kind": "person" }, "secret": "lwh_5mKq0Zp3Xw8Rt2Lv6Nb9Hc1Jd4Fg7Sa0Ye3Ui6Ok"}The request is invalid; errors lists what’s wrong.
RFC 9457 problem details.
object
For quota-exceeded, the window that is used up.
object
Null for a rolling window that hasn’t started.
organization when the organization’s budget is closer to running out than the member’s own limit.
Field-level problems (400 only).
object
JSON pointer into the request body.
Example
{ "type": "https://docs.asklucy.eu/errors/answer-in-progress", "quota": { "window": "five_hours", "limited_by": "personal", "request": { "status": "pending" } }}Headers
Section titled “Headers”Unique per request; quote it to support.
Missing, expired or invalid token.
RFC 9457 problem details.
object
For quota-exceeded, the window that is used up.
object
Null for a rolling window that hasn’t started.
organization when the organization’s budget is closer to running out than the member’s own limit.
Field-level problems (400 only).
object
JSON pointer into the request body.
Example
{ "type": "https://docs.asklucy.eu/errors/answer-in-progress", "quota": { "window": "five_hours", "limited_by": "personal", "request": { "status": "pending" } }}Headers
Section titled “Headers”Unique per request; quote it to support.
The token is valid but lacks the role this needs.
RFC 9457 problem details.
object
For quota-exceeded, the window that is used up.
object
Null for a rolling window that hasn’t started.
organization when the organization’s budget is closer to running out than the member’s own limit.
Field-level problems (400 only).
object
JSON pointer into the request body.
Example
{ "type": "https://docs.asklucy.eu/errors/answer-in-progress", "quota": { "window": "five_hours", "limited_by": "personal", "request": { "status": "pending" } }}Headers
Section titled “Headers”Unique per request; quote it to support.
No such object in your organization.
RFC 9457 problem details.
object
For quota-exceeded, the window that is used up.
object
Null for a rolling window that hasn’t started.
organization when the organization’s budget is closer to running out than the member’s own limit.
Field-level problems (400 only).
object
JSON pointer into the request body.
Example
{ "type": "https://docs.asklucy.eu/errors/answer-in-progress", "quota": { "window": "five_hours", "limited_by": "personal", "request": { "status": "pending" } }}Headers
Section titled “Headers”Unique per request; quote it to support.
The object isn’t in a state that allows this (e.g. Lucy is already answering).
RFC 9457 problem details.
object
For quota-exceeded, the window that is used up.
object
Null for a rolling window that hasn’t started.
organization when the organization’s budget is closer to running out than the member’s own limit.
Field-level problems (400 only).
object
JSON pointer into the request body.
Example
{ "type": "https://docs.asklucy.eu/errors/answer-in-progress", "quota": { "window": "five_hours", "limited_by": "personal", "request": { "status": "pending" } }}Headers
Section titled “Headers”Unique per request; quote it to support.
Storage for this isn’t configured on the server (e.g. …/errors/desktop-unavailable).
RFC 9457 problem details.
object
For quota-exceeded, the window that is used up.
object
Null for a rolling window that hasn’t started.
organization when the organization’s budget is closer to running out than the member’s own limit.
Field-level problems (400 only).
object
JSON pointer into the request body.
Example
{ "type": "https://docs.asklucy.eu/errors/answer-in-progress", "quota": { "window": "five_hours", "limited_by": "personal", "request": { "status": "pending" } }}Headers
Section titled “Headers”Unique per request; quote it to support.