Skip to content

Add a webhook or a schedule

POST
/agents/{agentId}/triggers
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.

agentId
required
string
/^agt_[A-Za-z0-9]+$/
Idempotency-Key
string
<= 255 characters

Any unique string (a UUID works). Retries with the same key return the first result.

Media typeapplication/json
object
type
required
string
Allowed values: webhook schedule
cron

Required for schedules.

string
timezone

Required for schedules.

string
callback_url
string | null format: uri
<= 2000 characters
input

At most 16 KB of JSON.

enabled
boolean
default: true
POST
{$request.body#/callback_url}

See AgentCallback.

Lucy-Signature
required
string

t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>" keyed with the trigger's token>.

Media typeapplication/json

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
run_id
required
string
agent_id
required
string
trigger_id
required
string
status
required

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.

string
Allowed values: queued running succeeded failed cancelled skipped
output
required
object
text
required
string | null
files
required
Array<object>
object
id
required
string
name
required
string
content_type
string
size_bytes
integer
url
required

A signed download link, valid 24 hours.

string format: uri
error
object
code
string
message
string
usage
required
object
steps
required

Tool calls.

integer
input_tokens
required
integer
output_tokens
required
integer
started_at
required
string | null format: date-time
finished_at
required
string format: date-time

Received. Anything else is retried, with backoff, for 24 hours.

Refused; retried like any other failure.

Created

Media typeapplication/json
object
id
required
string
agent_id
required
string
type
required
string
Allowed values: webhook schedule
enabled
required
boolean
webhook_url

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.

string | null format: uri
cron

Schedules: 5 fields (minute hour day-of-month month day-of-week), at most once every 15 minutes.

string | null
timezone

Schedules: the IANA time zone the cron is read in.

string | null
next_run_at

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.

string | null format: date-time
callback_url
required

Where Lucy POSTs each run’s result when it ends (see AgentCallback). https only, to a public address.

string | null format: uri
input
required

Fixed input given to every run it starts (any JSON), next to a webhook’s payload. Null for none.

secret_hint
required

The token’s prefix and last 4 characters, to tell tokens apart.

string
previous_secret_expires_at

After a rotation, until when the previous token (the previous URL) still works.

string | null format: date-time
last_fired_at
string | null format: date-time
created_by
One of:
object
id
required

Zitadel user ID.

string
name
required
string
email
string | null format: email
kind

service is a customer system’s Zitadel service user; agent is a service agent (its ID is the agt_ ID), the author of its runs’ messages.

string
Allowed values: person service agent
created_at
required
string format: date-time
updated_at
required
string format: date-time
secret
required

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.

string

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.

Media typeapplication/problem+json

RFC 9457 problem details.

object
type
required
string format: uri-reference
title
required
string
status
required
integer
detail
string
instance
string
request_id
string
quota

For quota-exceeded, the window that is used up.

object
window
required
string
Allowed values: five_hours week month
percent_used
required
number
<= 100
resets_at
required

Null for a rolling window that hasn’t started.

string | null format: date-time
limited_by
required

organization when the organization’s budget is closer to running out than the member’s own limit.

string
Allowed values: personal organization
request
One of:

A request as its member sees it, where they asked.

object
id
required
string
status
required
string
Allowed values: pending approved declined withdrawn
created_at
required
string format: date-time
decided_at
required
string | null format: date-time
note
required

What the admin who decided wrote back.

string | null
errors

Field-level problems (400 only).

Array<object>
object
field
required

JSON pointer into the request body.

string
message
required
string

Example

{
"type": "https://docs.asklucy.eu/errors/answer-in-progress",
"quota": {
"window": "five_hours",
"limited_by": "personal",
"request": {
"status": "pending"
}
}
}
X-Request-Id
string

Unique per request; quote it to support.

Missing, expired or invalid token.

Media typeapplication/problem+json

RFC 9457 problem details.

object
type
required
string format: uri-reference
title
required
string
status
required
integer
detail
string
instance
string
request_id
string
quota

For quota-exceeded, the window that is used up.

object
window
required
string
Allowed values: five_hours week month
percent_used
required
number
<= 100
resets_at
required

Null for a rolling window that hasn’t started.

string | null format: date-time
limited_by
required

organization when the organization’s budget is closer to running out than the member’s own limit.

string
Allowed values: personal organization
request
One of:

A request as its member sees it, where they asked.

object
id
required
string
status
required
string
Allowed values: pending approved declined withdrawn
created_at
required
string format: date-time
decided_at
required
string | null format: date-time
note
required

What the admin who decided wrote back.

string | null
errors

Field-level problems (400 only).

Array<object>
object
field
required

JSON pointer into the request body.

string
message
required
string

Example

{
"type": "https://docs.asklucy.eu/errors/answer-in-progress",
"quota": {
"window": "five_hours",
"limited_by": "personal",
"request": {
"status": "pending"
}
}
}
X-Request-Id
string

Unique per request; quote it to support.

The token is valid but lacks the role this needs.

Media typeapplication/problem+json

RFC 9457 problem details.

object
type
required
string format: uri-reference
title
required
string
status
required
integer
detail
string
instance
string
request_id
string
quota

For quota-exceeded, the window that is used up.

object
window
required
string
Allowed values: five_hours week month
percent_used
required
number
<= 100
resets_at
required

Null for a rolling window that hasn’t started.

string | null format: date-time
limited_by
required

organization when the organization’s budget is closer to running out than the member’s own limit.

string
Allowed values: personal organization
request
One of:

A request as its member sees it, where they asked.

object
id
required
string
status
required
string
Allowed values: pending approved declined withdrawn
created_at
required
string format: date-time
decided_at
required
string | null format: date-time
note
required

What the admin who decided wrote back.

string | null
errors

Field-level problems (400 only).

Array<object>
object
field
required

JSON pointer into the request body.

string
message
required
string

Example

{
"type": "https://docs.asklucy.eu/errors/answer-in-progress",
"quota": {
"window": "five_hours",
"limited_by": "personal",
"request": {
"status": "pending"
}
}
}
X-Request-Id
string

Unique per request; quote it to support.

No such object in your organization.

Media typeapplication/problem+json

RFC 9457 problem details.

object
type
required
string format: uri-reference
title
required
string
status
required
integer
detail
string
instance
string
request_id
string
quota

For quota-exceeded, the window that is used up.

object
window
required
string
Allowed values: five_hours week month
percent_used
required
number
<= 100
resets_at
required

Null for a rolling window that hasn’t started.

string | null format: date-time
limited_by
required

organization when the organization’s budget is closer to running out than the member’s own limit.

string
Allowed values: personal organization
request
One of:

A request as its member sees it, where they asked.

object
id
required
string
status
required
string
Allowed values: pending approved declined withdrawn
created_at
required
string format: date-time
decided_at
required
string | null format: date-time
note
required

What the admin who decided wrote back.

string | null
errors

Field-level problems (400 only).

Array<object>
object
field
required

JSON pointer into the request body.

string
message
required
string

Example

{
"type": "https://docs.asklucy.eu/errors/answer-in-progress",
"quota": {
"window": "five_hours",
"limited_by": "personal",
"request": {
"status": "pending"
}
}
}
X-Request-Id
string

Unique per request; quote it to support.

The object isn’t in a state that allows this (e.g. Lucy is already answering).

Media typeapplication/problem+json

RFC 9457 problem details.

object
type
required
string format: uri-reference
title
required
string
status
required
integer
detail
string
instance
string
request_id
string
quota

For quota-exceeded, the window that is used up.

object
window
required
string
Allowed values: five_hours week month
percent_used
required
number
<= 100
resets_at
required

Null for a rolling window that hasn’t started.

string | null format: date-time
limited_by
required

organization when the organization’s budget is closer to running out than the member’s own limit.

string
Allowed values: personal organization
request
One of:

A request as its member sees it, where they asked.

object
id
required
string
status
required
string
Allowed values: pending approved declined withdrawn
created_at
required
string format: date-time
decided_at
required
string | null format: date-time
note
required

What the admin who decided wrote back.

string | null
errors

Field-level problems (400 only).

Array<object>
object
field
required

JSON pointer into the request body.

string
message
required
string

Example

{
"type": "https://docs.asklucy.eu/errors/answer-in-progress",
"quota": {
"window": "five_hours",
"limited_by": "personal",
"request": {
"status": "pending"
}
}
}
X-Request-Id
string

Unique per request; quote it to support.

Storage for this isn’t configured on the server (e.g. …/errors/desktop-unavailable).

Media typeapplication/problem+json

RFC 9457 problem details.

object
type
required
string format: uri-reference
title
required
string
status
required
integer
detail
string
instance
string
request_id
string
quota

For quota-exceeded, the window that is used up.

object
window
required
string
Allowed values: five_hours week month
percent_used
required
number
<= 100
resets_at
required

Null for a rolling window that hasn’t started.

string | null format: date-time
limited_by
required

organization when the organization’s budget is closer to running out than the member’s own limit.

string
Allowed values: personal organization
request
One of:

A request as its member sees it, where they asked.

object
id
required
string
status
required
string
Allowed values: pending approved declined withdrawn
created_at
required
string format: date-time
decided_at
required
string | null format: date-time
note
required

What the admin who decided wrote back.

string | null
errors

Field-level problems (400 only).

Array<object>
object
field
required

JSON pointer into the request body.

string
message
required
string

Example

{
"type": "https://docs.asklucy.eu/errors/answer-in-progress",
"quota": {
"window": "five_hours",
"limited_by": "personal",
"request": {
"status": "pending"
}
}
}
X-Request-Id
string

Unique per request; quote it to support.