Agent configuration
Agents can be created and managed through the Backoffice UI at the Agents page in the Admin sidebar or programmatically via the GraphQL API using the agents query and related mutations.
Agent properties
Each agent has the following properties:
Identity
| Field | Description |
|---|---|
id | Unique identifier |
names | Localized display names (per language) |
descriptions | Localized descriptions (per language) |
active | Whether the agent is currently enabled |
Behavior
| Field | Description |
|---|---|
trigger | How the agent is activated: CHAT (user types a message) or BUTTON (user clicks an action button) |
interactionMode | MULTI_TURN (supports follow-up messages) or SINGLE_TURN (one request, one response). Independent of trigger type |
types | The UI contexts where the agent appears. Values must be in SCREAMING_SNAKE_CASE |
Integration
| Field | Description |
|---|---|
webhookUrl | The external endpoint that processes the agent's requests (required, max 2048 characters) |
webhookTimeoutMs | Timeout in milliseconds for webhook requests (required) |
UX
| Field | Description |
|---|---|
welcomeMessages | Localized messages displayed when the agent is activated |
buttonLabels | Localized labels for the agent's button in the UI |
Built-in agent types
The Propeller UI uses the following agent types:
| Type | Where it appears |
|---|---|
SALES_HUB_QUOTE_EDITOR | Quote editor in Sales Hub |
SALES_HUB_ORDER_EDITOR | Order editor in Sales Hub |
SALES_HUB_QUOTE_REQUEST_EDITOR | Quote request editor in Sales Hub |
SALES_HUB_COMPANY | Company detail page |
BACKOFFICE_PRODUCTS | Products and clusters page in PIM |
Implementation partners can also define custom types (for example WEBSHOP_PRODUCT_DETAIL or FRONTEND_SHOPPING_BASKET) for use in their own frontends. See Embedding agents in your frontend.
Querying agents
Use the agents query to retrieve agents. You can filter by types and active status to retrieve only agents relevant to a specific view:
query agents($input: AgentSearchInput) {
agents(input: $input) {
itemsFound
items {
id
active
names { language value }
descriptions { language value }
trigger
interactionMode
types
webhookUrl
webhookTimeoutMs
welcomeMessages { language value }
}
}
}
{
"input": {
"types": ["SALES_HUB_ORDER_EDITOR"],
"active": true
}
}
Creating an agent
Agents are created with the agentCreate mutation. This is where you wire up the trigger type, the UI views it should appear in, the webhook endpoint and any security credentials.
AgentCreateInput fields
| Field | Type | Required | Description |
|---|---|---|---|
names | [LocalizedStringInput!]! | Yes | Display names. Unique language entries |
descriptions | [LocalizedStringInput!] | No | Descriptions. Unique language entries |
welcomeMessages | [LocalizedStringInput!] | No | Messages shown when the agent is activated |
buttonLabels | [LocalizedStringInput!] | No | Labels for the agent button in the UI |
active | Boolean! | Yes | Whether the agent is active on creation |
types | [String!]! | Yes | UI contexts. Must be SCREAMING_SNAKE_CASE |
trigger | AgentTrigger! | Yes | CHAT or BUTTON |
interactionMode | AgentInteractionMode! | Yes | SINGLE_TURN or MULTI_TURN |
webhookUrl | String! | Yes | Webhook endpoint. Max 2048 characters |
webhookTimeoutMs | Int! | Yes | Webhook timeout in milliseconds |
webhookSignatureSalt | String | No | Salt for HMAC-SHA256 payload signing |
webhookBasicAuthUsername | String | No | Basic auth username. Must pair with password |
webhookBasicAuthPassword | String | No | Basic auth password. Must pair with username |
Mutation
mutation agentCreate($input: AgentCreateInput!) {
agentCreate(input: $input) {
id
active
names { language value }
descriptions { language value }
trigger
interactionMode
types
webhookUrl
webhookTimeoutMs
welcomeMessages { language value }
createdAt
lastModifiedAt
}
}
Example: Margin Validator agent
{
"input": {
"names": [
{ "language": "NL", "value": "Margin Validator" }
],
"descriptions": [
{ "language": "NL", "value": "Validates quote and order margins" }
],
"trigger": "BUTTON",
"interactionMode": "SINGLE_TURN",
"active": true,
"types": ["SALES_HUB_QUOTE_EDITOR"],
"webhookUrl": "https://your-workflow-engine.com/webhook/margin-validator",
"webhookTimeoutMs": 30000,
"welcomeMessages": [
{
"language": "NL",
"value": "This message is shown in the modal when opening the agent"
}
],
"webhookSignatureSalt": "your-secret-salt",
"webhookBasicAuthUsername": "webhook-user",
"webhookBasicAuthPassword": "webhook-pass"
}
}
All three authentication fields are optional. You can use basic auth, signature verification, both or neither.
Webhook authentication
HMAC signature verification
When webhookSignatureSalt is configured, Propeller includes an X-Propeller-Signature header with every webhook request in the format sha256=<hex-digest>.
To verify the payload is authentic:
- JSON-stringify the request payload
- Generate an HMAC-SHA256 hash using the configured salt and the stringified payload
- Compare the result with the received signature using a timing-safe comparison
Node.js example:
const crypto = require('crypto');
function verifySignature(salt, payload, signature) {
const expectedSig = crypto
.createHmac('sha256', salt)
.update(JSON.stringify(payload), 'utf8')
.digest('hex');
const receivedSig = signature.replace('sha256=', '');
return crypto.timingSafeEqual(
Buffer.from(expectedSig, 'hex'),
Buffer.from(receivedSig, 'hex')
);
}
Basic authentication
When webhookBasicAuthUsername and webhookBasicAuthPassword are configured, Propeller adds a standard Authorization: Basic ... header to webhook requests. Both fields must be provided together or both omitted.
See also
- Conversations for trigger and interaction mode details
- Webhook integration for the webhook request/response contract
- Embedding agents in your frontend for custom agent types