Skip to main content

Agent Webhook

An external system can send a configured event to DesireCore so the target Agent processes its content in the background. This is useful for business notifications, monitoring events, and messages from other applications.

Instance owners can create events, select tools, and obtain a dedicated secret through the management API. External services that only send events obtain the configured event details and secret from the administrator.

First use the authenticated handshake and check capabilities.webhookManagement. Only an instance reporting true supports the management steps below. If the field is missing or false, this instance cannot create or change events through these APIs. Existing valid configurations can still use the trigger request.

Before calling​

InformationSource and requirements
BASE_URLThe Agent Service address supplied by the administrator; see Connection and authentication. The public documentation website is not a service address.
AGENT_IDThe target Agent ID supplied by the administrator. A display name cannot replace it. Webhooks must be enabled for this Agent.
eventAn existing event name supplied by the administrator, such as demo.ping. It must match exactly.
WEBHOOK_SECRETThe target Agent's dedicated Webhook secret. Store and inject it through the sender's secret management system. Coordinate rotation with the administrator and update the sender.
Event behaviorConfirm the expected fields, permitted operations, and result delivery. Trigger requests do not contain tool or file permission settings; actual operations depend on the selected tools and file scope.

External callers need a configured Webhook secret. A remote instance rejects triggers without one; a local instance without one also cannot be triggered through the external calling method described here. This secret has a different purpose from an instance access token or a model provider's API key. Configure the sender with the dedicated Webhook secret supplied by the administrator.

The sender must be able to reach the instance address. A desktop instance's loopback address is only reachable from the same computer; an external server needs a reachable service address supplied by the administrator. The DesireCore service must remain running.

Create an event and select execution permissions​

The standalone instance owner performs these steps using X-Agent-Service-Token from Connection and authentication. A Webhook secret grants triggering access, not event management or receipt access. The commands require curl and jq.

1. Read events and available tools​

Use the existing instance address, owner token, and target Agent ID. Obtain the Agent ID from the Agent list. The saved management response reports whether a secret exists without returning its value.

BASE_URL='https://your-instance.example'
AGENT_ID='your-agent-id'
AGENT_SERVICE_TOKEN='replace-with-your-existing-instance-token'
umask 077

curl --fail-with-body --silent --show-error \
--header "X-Agent-Service-Token: ${AGENT_SERVICE_TOKEN}" \
"${BASE_URL}/api/agents/${AGENT_ID}/webhooks" \
--output webhook-config.json

jq '{enabled,hasSecret,events,availableTools}' webhook-config.json
Response fieldMeaning
enabledWhether the Agent's Webhook endpoint is enabled.
hasSecretWhether a secret is configured. Reading does not return its value again.
eventsEach existing event's event, promptTemplate, maxTurns, and toolIds.
availableToolsThe id, name, riskLevel, and requiresConfirmation of tools currently available for selection.

Choose the IDs of tools the event needs. toolIds: [] authorizes no tools. This example selects SendUserMessage to deliver the test result to the user's conversation. If it is absent from availableTools, adjust the target Agent's tool configuration and read the list again.

Select only tools needed for the event's work. This example needs only SendUserMessage. Add tools such as Write or Bash when the event needs file writing or command execution. These tools can modify configuration files within their effective file scope, including Agent and event configuration in that scope. Tool selection and file scope use the instance's existing permission mechanism; granting write access also requires considering which configurations it can change.

2. Save demo.ping​

The management API accepts the event template, selected tool IDs, and maximum turn count. The service determines the corresponding tools and current file access scope when saving. You do not need to supply tool definitions or permission objects. Execution remains subject to the Agent's current permissions.

FieldRequirements
Event name (:event in the path)1–128 characters. Start with an ASCII letter or digit; remaining characters may be ASCII letters, digits, ., _, or -. constructor, prototype, and __proto__ are not allowed.
promptTemplateRequired nonempty string, at most 32,768 characters. Supports the {{key}} fields described below.
toolIdsRequired array of IDs from availableTools, without duplicates. Maximum 512 items; an empty array grants no tool permissions.
maxTurnsOptional integer from 1 to 100; defaults to 5.

PUT creates or replaces the named event and enables the Agent's Webhook endpoint. Replacement updates both the template and tool selection; saving again captures the current file access scope. The request body limit is 128 KiB.

If saving returns 409 with error: "webhook_configuration_changed", the Agent configuration changed during the save, and this event change was not committed. Read events and available tools again with GET, confirm the template, tool selection, and current file permissions, then save again.

SEND_USER_MESSAGE_TOOL_ID="$(jq -er \
'[.availableTools[] | select(.name == "SendUserMessage")] | if length == 1 then .[0].id else error("SendUserMessage is not available") end' \
webhook-config.json)"

jq -n --arg tool "${SEND_USER_MESSAGE_TOOL_ID}" \
--arg prompt 'Received message: {{message}}. Use SendUserMessage to send this received message to the user.' \
'{promptTemplate:$prompt,toolIds:[$tool],maxTurns:5}' \
> webhook-event.json

curl --fail-with-body --silent --show-error --request PUT \
--header "X-Agent-Service-Token: ${AGENT_SERVICE_TOKEN}" \
--header 'Content-Type: application/json' \
--data-binary @webhook-event.json \
"${BASE_URL}/api/agents/${AGENT_ID}/webhooks/events/demo.ping" \
--output webhook-write.json

A successful save returns 200:

{
"success": true,
"enabled": true,
"event": "demo.ping",
"secret": "<generated-webhook-secret>"
}

secret appears only when this save generated the initial secret. Immediately store it through the sender's secret management system. Keep response files containing secrets out of public repositories and logs. When a secret already exists, the response contains only success, enabled, and event.

If the saved secret or its initial response is lost, rotate the secret to obtain a new value. Reading configuration or saving the event again does not retrieve the old secret.

3. Trigger and observe delivery​

Set WEBHOOK_SECRET to the generated or rotated value, use Send one request below to trigger demo.ping, and follow Observe the result to verify user delivery. The Agent needs a working model configuration and must actually call its authorized message tool. Saving the event and receiving the trigger do not replace this verification.

Pause, delete, and rotate secrets​

All management operations below use the instance access token. They change subsequent trigger configuration without stopping background runs that have already been accepted.

OperationRequestSuccessful response
Pause all eventsPATCH /api/agents/:id/webhooks with JSON {"enabled":false}{"success":true,"enabled":false}
Enable existing eventsSame path with JSON {"enabled":true}{"success":true,"enabled":true}; requires existing events and a secret.
Delete one eventDELETE /api/agents/:id/webhooks/events/:event, no body{"success":true,"enabled":...}; deleting the last event pauses the endpoint.

Rotate the secret​

All events for one Agent share a Webhook secret. After rotation, the old secret can no longer authenticate subsequent triggers, and all senders must update it. Existing runs continue processing.

curl --fail-with-body --silent --show-error --request POST \
--header "X-Agent-Service-Token: ${AGENT_SERVICE_TOKEN}" \
"${BASE_URL}/api/agents/${AGENT_ID}/webhooks/secret/rotate" \
--output webhook-secret.json

Send no body. Success returns 200 {"secret":"<new-webhook-secret>"}. Save the new value in the sender's secret management configuration. If the rotation response is lost, configuration reads cannot retrieve the secret; rotate again and update all senders.

Request​

POST /api/webhook/:agent_id
Authorization: Bearer <Webhook secret>
Content-Type: application/json

Use the Bearer prefix shown above, immediately followed by the secret. The request body limit is 1 MiB (1,048,576 bytes) for the entire JSON request.

FieldTypeRequiredDescription
eventstringYesAn event name already configured for the target Agent.
payloadobjectNoFields required by the event template. Omission is treated as an empty object.

Only event and payload are accepted at the top level. payload may contain the JSON fields agreed for the event, but must be an object rather than an array or string.

{
"event": "demo.ping",
"payload": {
"message": "Test event: please confirm receipt."
}
}

Transform a third party's original notification into this structure before sending it. For example, a GitHub push integration must map the event name and payload and add the Bearer secret required here. This endpoint does not directly validate GitHub signature headers.

Template fields​

The administrator's prompt template uses {{key}} to read a matching top-level field from payload. For example, Received message: {{message}} becomes Received message: Test event: please confirm receipt. for the request above.

  • Strings, numbers, and booleans become text. Objects and arrays become JSON text.
  • Missing fields and null values leave the original placeholder, such as {{message}}, unchanged.
  • Nested paths such as {{user.name}} are not supported. Put the required value in an agreed top-level field.

Supply the fields required by the event so the Agent does not receive unresolved placeholders.

Send one request​

This example uses demo.ping created above, or an event with the same name already configured by the administrator, with payload.message. Replace the instance address and Agent ID, and set WEBHOOK_SECRET through the sender's secret management system. Update the JSON body if your event name or fields differ.

BASE_URL='https://your-instance.example'
AGENT_ID='your-agent-id'

curl --include --request POST \
"${BASE_URL%/}/api/webhook/${AGENT_ID}" \
--header "Authorization: Bearer ${WEBHOOK_SECRET}" \
--header 'Content-Type: application/json' \
--data '{"event":"demo.ping","payload":{"message":"Test event: please confirm receipt."}}'

A received event returns 200 OK:

{
"accepted": true,
"agentId": "your-agent-id",
"event": "demo.ping"
}

accepted: true means the event was received and background processing follows. It does not establish that a model has started, a tool call succeeded, or the task completed. The response contains no Run ID, request ID, or final answer. A subsequent background failure cannot change the already returned 200 response.

Observe the result​

Before calling, ask the administrator how this event is expected to deliver its result. If the event is authorized to use SendUserMessage and calls it during the run, successfully stored messages or attachments appear in the target Agent's conversation in DesireCore connected to the same instance. Reopen that Agent's conversation to load existing deliveries.

An ordinary final model answer is not automatically delivered there. A missing message may mean the event is still running, sent no message, or encountered a permission or delivery failure. It does not establish success or failure. An existing delivery also does not establish that all subsequent operations in that run completed.

The instance owner can also read durable delivery records:

curl --fail-with-body --silent --show-error \
--header "X-Agent-Service-Token: ${AGENT_SERVICE_TOKEN}" \
"${BASE_URL}/api/agents/${AGENT_ID}/schedule-messages?limit=20&offset=0"

The response is {"items":[...],"total":...,"limit":20,"offset":0}. Webhook deliveries have origin: "webhook" and the event name in displayName; the message is usually in delivery.message and attachment references in delivery.attachments. A delivery degraded to plain text uses text. Only records readable by the current identity are returned. limit defaults to 50 and has a maximum of 200; offset starts at 0.

This is the Agent's delivery list, not the terminal status of a specific trigger. Repeated calls to the same event may have interleaved records, and an empty list does not establish execution failure. To identify business events, include the sender's business identifier in the agreed payload and delivered message. This does not add deduplication or a unique Run lookup to the trigger endpoint.

If the event provides no user delivery, the caller described here receives only the accepted receipt feedback; the administrator needs to inspect logs for execution details. This endpoint provides no way to query completion or a final result for this specific request. To investigate a failure or timeout, give the instance administrator the target Agent ID, event name, sending time, and HTTP response so they can inspect service logs. Keep the secret out of troubleshooting records.

If your application needs a unique execution identifier for every call, terminal status polling, or a result callback, first confirm an appropriate integration method with the administrator.

Duplicate calls and timeouts​

This endpoint has no idempotency key or request deduplication. Sending the same request twice may execute it twice. Including a business event ID in payload does not automatically enable deduplication.

If the sender times out or disconnects, receipt may be unknown: the service may already have received the event and started processing it. Save the sending time, event name, and any available response, then check what happened. For events that perform external actions, do not resend unconditionally just because no response arrived.

Background processing has its own execution timeout controls. Failure or timeout can occur after successful receipt. Increasing the sender's HTTP timeout does not make this asynchronous endpoint return a final result.

Management errors​

Management errors use stable identifiers in error. Field validation failures may also return details.

HTTP statuserrorAction
400invalid_webhook_management_requestCheck required fields, types, and limits. Send no body when rotating a secret.
400invalid_webhook_eventUse a name matching the event naming rules.
400webhook_tool_unavailableRead availableTools again and choose exact IDs that remain available.
400webhook_events_requiredSave an event and confirm that a secret exists before enabling.
400invalid_agent_idCheck the target Agent ID.
401 / 403Authentication/governance rejection, or webhook_owner_requiredUse the target instance owner's token. A Webhook secret cannot manage events.
404agent_not_found / webhook_event_not_foundCheck the target Agent and the event being deleted.
409webhook_configuration_changedThis save was not committed. Read configuration and available tools again, confirm permissions, and retry the save.
409webhook_configuration_invalidHave the administrator repair existing configuration before saving again.
413Save body too largeReduce the entire event save request to no more than 128 KiB.
500webhook_management_failedAsk the administrator to inspect service logs and check whether the change took effect before proceeding.

Trigger errors​

Inspect the HTTP status and the actual error field first. Some errors also include message or details. Do not expect every response to use a fixed success/data/error envelope.

HTTP statusError or conditionCaller action
400Invalid request body, possibly with validation detailsCheck that the JSON body is an object, event is a string, and payload is an object. Remove other top-level fields.
400Unknown event type: ...Check the supplied event name, capitalization, and target Agent.
400Invalid JSONCorrect JSON syntax before resending.
401Invalid webhook secretCheck Authorization: Bearer ... and the current secret. Confirm that the sender has received any secret rotation.
401Invalid embedded instance tokenThis local event lacks the secret needed for external calling. Ask the administrator for an event with a configured secret.
403webhook_secret_requiredThe target Agent on the remote instance has no valid Webhook secret. Ask the administrator to complete configuration.
404Agent not foundCheck the instance address and target Agent ID.
404Webhook not enabled for this agentAsk the administrator to confirm that events are enabled for the target Agent.
413Request body too largeReduce the entire JSON request to no more than 1 MiB, following the event's payload requirements.
415Unsupported media typeUse Content-Type: application/json.
500Failed to parse agent.jsonAsk the administrator to check the Agent configuration. Repeated sending cannot repair it.

Reverse proxies and connection failures may produce other errors; see Errors and troubleshooting. Fix requests that were explicitly rejected before sending again. Treat a lost response as an unknown outcome as described above.